From ba729cb2181e097a024f808e46bbcd24c56d0508 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Thu, 4 Jul 2019 10:51:02 +0300 Subject: [PATCH 01/10] Fix for unsupported courses --- .../gr/thmmy/mthmmy/activities/upload/UploadsCourse.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsCourse.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsCourse.java index 8fe986c9..1a2f55ae 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsCourse.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsCourse.java @@ -59,8 +59,9 @@ class UploadsCourse { if(foundKey==null){ Timber.w("Couldn't find course that matches %s", retrievedCourse); Bundle bundle = new Bundle(); - bundle.putString("COURSE_NAME", retrievedCourse); - BaseApplication.getInstance().logFirebaseAnalyticsEvent("UNSUPPORTED_UPLOADS_COURSE", bundle); + bundle.putString("course_name", retrievedCourse); + BaseApplication.getInstance().logFirebaseAnalyticsEvent("unsupported_uploads_course", bundle); + return null; } return uploadsCourses.get(foundKey); From 35b15e7fb15715aa2eb46f38df84330ea350783e Mon Sep 17 00:00:00 2001 From: Ezerous Date: Thu, 4 Jul 2019 10:56:43 +0300 Subject: [PATCH 02/10] Fix for unsupported courses --- .../activities/upload/UploadActivity.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java index d6fb274a..dcf9b90e 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java @@ -940,14 +940,16 @@ public class UploadActivity extends BaseActivity { String retrievedCourse = maybeCourse.replaceAll("-", "").replace("(ΝΠΣ)", "").trim(); String retrievedSemester = maybeSemester.replaceAll("-", "").trim().substring(0, 1); - UploadsCourse foundUploadsCourse = UploadsCourse.findCourse(retrievedCourse, uploadsCourses); - - if(foundUploadsCourse != null){ - uploadsCourse = foundUploadsCourse; - semester = retrievedSemester; - Timber.d("Selected course: %s, semester: %s", uploadsCourse.getName(), semester); - titleDescriptionBuilderButton.setEnabled(true); - return; + if(!retrievedCourse.isEmpty()){ + UploadsCourse foundUploadsCourse = UploadsCourse.findCourse(retrievedCourse, uploadsCourses); + + if(foundUploadsCourse != null){ + uploadsCourse = foundUploadsCourse; + semester = retrievedSemester; + Timber.d("Selected course: %s, semester: %s", uploadsCourse.getName(), semester); + titleDescriptionBuilderButton.setEnabled(true); + return; + } } titleDescriptionBuilderButton.setEnabled(false); From d91dfcf477c623c97251601ce6f42690b892563e Mon Sep 17 00:00:00 2001 From: Ezerous Date: Sat, 6 Jul 2019 15:37:14 +0300 Subject: [PATCH 03/10] Uploads improvements --- .../activities/upload/UploadActivity.java | 44 ++++++------------- .../activities/upload/UploadsCourse.java | 5 ++- app/src/main/res/values/uploads_courses.xml | 4 ++ 3 files changed, 21 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java index dcf9b90e..6d0a2d9b 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java @@ -130,7 +130,7 @@ public class UploadActivity extends BaseActivity { private EditText uploadTitle; private EditText uploadFilename; private EditText uploadDescription; - private AppCompatButton titleDescriptionBuilderButton; + private AppCompatButton generateFieldsButton; private LinearLayout filesListView; @Override @@ -174,9 +174,9 @@ public class UploadActivity extends BaseActivity { rootCategorySpinner = findViewById(R.id.upload_spinner_category_root); rootCategorySpinner.setOnItemSelectedListener(new CustomOnItemSelectedListener(uploadRootCategories)); - titleDescriptionBuilderButton = findViewById(R.id.upload_title_description_builder); - titleDescriptionBuilderButton.setEnabled(false); - titleDescriptionBuilderButton.setOnClickListener(view -> { + generateFieldsButton = findViewById(R.id.upload_title_description_builder); + generateFieldsButton.setEnabled(false); + generateFieldsButton.setOnClickListener(view -> { if(uploadsCourse!=null && !uploadsCourse.getName().equals("") && !semester.equals("")){ Intent intent = new Intent(UploadActivity.this, UploadFieldsBuilderActivity.class); Bundle builderExtras = new Bundle(); @@ -410,7 +410,7 @@ public class UploadActivity extends BaseActivity { } else { //Renders the already parsed data updateUIElements(); - titleDescriptionBuilderButton.setEnabled(true); + generateFieldsButton.setEnabled(true); } Resources res = getResources(); @@ -841,7 +841,7 @@ public class UploadActivity extends BaseActivity { } categorySelected = parentCategories.get(position).getValue(); - setCourseAndSemester(); + generateFieldsButton.setEnabled(false); //Adds new sub-category spinner if (parentCategories.get(position).hasSubCategories()) { @@ -882,6 +882,8 @@ public class UploadActivity extends BaseActivity { } } } + else + setCourseAndSemester(); } @Override @@ -890,21 +892,13 @@ public class UploadActivity extends BaseActivity { private void setCourseAndSemester(){ uploadsCourse = null; semester = ""; - - if (categorySelected.equals("-1")) { - titleDescriptionBuilderButton.setEnabled(false); - return; - } + if (categorySelected.equals("-1")) return; int numberOfSpinners = categoriesSpinners.getChildCount(); - if (numberOfSpinners < 3) { - titleDescriptionBuilderButton.setEnabled(false); - return; - } + if (numberOfSpinners < 3) return; - String maybeSemester = ""; - String maybeCourse = ""; + String maybeSemester, maybeCourse; if (numberOfSpinners == 5) { if (((AppCompatSpinnerWithoutDefault) categoriesSpinners.getChildAt(numberOfSpinners - 1)). @@ -927,15 +921,8 @@ public class UploadActivity extends BaseActivity { categoriesSpinners.getChildAt(numberOfSpinners - 1)).getSelectedItem(); } - if (!maybeSemester.contains("εξάμηνο") && !maybeSemester.contains("Εξάμηνο")) { - titleDescriptionBuilderButton.setEnabled(false); - return; - } - - if (maybeCourse == null) { - titleDescriptionBuilderButton.setEnabled(false); - return; - } + if (!maybeSemester.contains("εξάμηνο") && !maybeSemester.contains("Εξάμηνο")) return; + if (maybeCourse == null) return; String retrievedCourse = maybeCourse.replaceAll("-", "").replace("(ΝΠΣ)", "").trim(); String retrievedSemester = maybeSemester.replaceAll("-", "").trim().substring(0, 1); @@ -947,12 +934,9 @@ public class UploadActivity extends BaseActivity { uploadsCourse = foundUploadsCourse; semester = retrievedSemester; Timber.d("Selected course: %s, semester: %s", uploadsCourse.getName(), semester); - titleDescriptionBuilderButton.setEnabled(true); - return; + generateFieldsButton.setEnabled(true); } } - - titleDescriptionBuilderButton.setEnabled(false); } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsCourse.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsCourse.java index 1a2f55ae..12f0475f 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsCourse.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsCourse.java @@ -52,8 +52,9 @@ class UploadsCourse { String foundKey = null; for (Map.Entry entry : uploadsCourses.entrySet()) { String key = entry.getKey(); - if ((key.contains(retrievedCourse))&& (foundKey==null || key.length()>foundKey.length())) - foundKey = key; + if ((key.contains(retrievedCourse) || retrievedCourse.contains(key)) + && (foundKey==null || key.length()>foundKey.length())) + foundKey = key; } if(foundKey==null){ diff --git a/app/src/main/res/values/uploads_courses.xml b/app/src/main/res/values/uploads_courses.xml index 8f872389..6fb45b37 100644 --- a/app/src/main/res/values/uploads_courses.xml +++ b/app/src/main/res/values/uploads_courses.xml @@ -35,6 +35,7 @@ Διακριτά Μαθηματικά:Διακριτά Μαθηματικά:Diakrita Διακριτά μαθηματικά:Διακριτά Μαθηματικά:Diakrita Διανεμημένη Παραγωγή:Διανεμημένη Παραγωγή:Dian_Paragogi + Διατάξεις Υψηλών Συχνοτήτων:ΔΥΣ:DYS Διαφορικές Εξισώσεις:Διαφορικές:Diaforikes Διαχείριση Συστημάτων Ηλεκτρικής Ενέργειας:ΔΣΗΕ:DSHE Δομές Δεδομένων:Δομ. Δεδομ.:Domes_Dedomenon @@ -63,6 +64,7 @@ Ηλεκτρικά Κυκλώματα III:Κυκλώματα 3:Kyklomata_I Ηλεκτρικές Μετρήσεις I:Μετρήσεις 1:Metriseis_I Ηλεκτρικές Μετρήσεις II:Μετρήσεις 2:Metriseis_II + Ηλεκτρικές Μηχανές I:Μηχανές I:Mixanes_I Ηλεκτρικές Μηχανές Α\':Μηχανές Α:Mixanes_A Ηλεκτρικές Μηχανές Β\':Μηχανές Β:Mixanes_B Ηλεκτρικές Μηχανές Γ\':Μηχανές Γ:Mixanes_C @@ -132,6 +134,8 @@ Τεχνολογία Ηλεκτροτεχνικών Υλικών:Ηλεκτροτεχνικά Υλικά:Ilektrotexnika_Ylika Τεχνολογία Λογισμικού:Τεχνολογία Λογισμικού:SE Τηλεοπτικά Συστήματα:Τηλεοπτικά:Tileoptika + Τηλεπικοινωνιακά Συστήματα I:Τηλεπικοινωνιακά I:Tilepikoinoniaka_I + Τηλεπικοινωνιακά Συστήματα II:Τηλεπικοινωνιακά II:Tilepikoinoniaka_II Τηλεπικοινωνιακή Ηλεκτρονική:Τηλεπ. Ηλεκτρ.:Tilep_Ilektr Υπολογιστικές Μέθοδοι στα Ενεργειακά Συστήματα:ΥΜΕΣ:YMES Υπολογιστικός Ηλεκτρομαγνητισμός:Υπολογιστικός Η/Μ:Ypologistikos_HM From 9a61ffead17eb04d4b68286647228840e47deb18 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Sun, 7 Jul 2019 20:11:40 +0300 Subject: [PATCH 04/10] Uploads improvements (2) --- .../gr/thmmy/mthmmy/activities/upload/UploadActivity.java | 8 +++++--- .../activities/upload/UploadFieldsBuilderActivity.java | 6 +++--- app/src/main/res/values/uploads_courses.xml | 3 ++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java index 6d0a2d9b..0b1195d2 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java @@ -924,15 +924,17 @@ public class UploadActivity extends BaseActivity { if (!maybeSemester.contains("εξάμηνο") && !maybeSemester.contains("Εξάμηνο")) return; if (maybeCourse == null) return; - String retrievedCourse = maybeCourse.replaceAll("-", "").replace("(ΝΠΣ)", "").trim(); - String retrievedSemester = maybeSemester.replaceAll("-", "").trim().substring(0, 1); + String retrievedCourse = maybeCourse.replaceAll("-", "") + .replaceAll("\\((πρώην|πρωην).*\\)","") + .replace("(ΝΠΣ)", "") + .trim(); if(!retrievedCourse.isEmpty()){ UploadsCourse foundUploadsCourse = UploadsCourse.findCourse(retrievedCourse, uploadsCourses); if(foundUploadsCourse != null){ uploadsCourse = foundUploadsCourse; - semester = retrievedSemester; + semester = maybeSemester.replaceAll("-", "").trim().substring(0, 1); Timber.d("Selected course: %s, semester: %s", uploadsCourse.getName(), semester); generateFieldsButton.setEnabled(true); } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadFieldsBuilderActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadFieldsBuilderActivity.java index ffa6f26e..f7eb6e0d 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadFieldsBuilderActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadFieldsBuilderActivity.java @@ -156,11 +156,11 @@ public class UploadFieldsBuilderActivity extends BaseActivity { private String buildTitle() { switch (typeRadio.getCheckedRadioButtonId()) { case R.id.upload_fields_builder_radio_button_exams: - return courseMinifiedName + " - " + "Θέματα εξετάσεων " + getPeriod() + " " + year.getText().toString(); + return "[" + courseMinifiedName + "] - " + "Θέματα εξετάσεων " + getPeriod() + " " + year.getText().toString(); case R.id.upload_fields_builder_radio_button_exam_solutions: - return courseMinifiedName + " - " + "Λύσεις θεμάτων " + getPeriod() + " " + year.getText().toString(); + return "[" + courseMinifiedName + "] - " + "Λύσεις θεμάτων " + getPeriod() + " " + year.getText().toString(); case R.id.upload_fields_builder_radio_button_notes: - return courseMinifiedName + " - " + "Σημειώσεις παραδόσεων " + year.getText().toString(); + return "[" + courseMinifiedName + "] - " + "Σημειώσεις παραδόσεων " + year.getText().toString(); default: return null; } diff --git a/app/src/main/res/values/uploads_courses.xml b/app/src/main/res/values/uploads_courses.xml index 6fb45b37..51781f41 100644 --- a/app/src/main/res/values/uploads_courses.xml +++ b/app/src/main/res/values/uploads_courses.xml @@ -111,7 +111,8 @@ Σήματα και Συστήματα:Σήματα & Συστήματα:Analog_Sima Σερβοκινητήρια Συστήματα:Σέρβο:Servo Σταθμοί Παραγωγής Ηλεκτρικής Ενέργειας:ΣΠΗΕ:SPHE - Στοχαστικό Σήμα:Στοχ. Σήμα:Stox_Sima + Στοχαστικά Σήματα και Διαδικασίες:Στοχαστικό:Stochastic + Στοχαστικό Σήμα:Στοχαστικό:Stochastic Συστήματα Αυτομάτου Ελέγχου I:ΣΑΕ 1:SAE_I Συστήματα Αυτομάτου Ελέγχου II:ΣΑΕ 2:SAE_II Συστήματα Αυτομάτου Ελέγχου III:ΣΑΕ 3:SAE_III From e35688cdf15ca01182e76cb2d1d1514c5428f799 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Mon, 16 Sep 2019 17:59:51 +0300 Subject: [PATCH 05/10] Uploads fix --- app/build.gradle | 4 +- .../activities/upload/UploadActivity.java | 3 +- .../multipart/MultipartUploadRequest.java | 99 +++++++++++ .../upload/multipart/MultipartUploadTask.java | 160 ++++++++++++++++++ 4 files changed, 263 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadRequest.java create mode 100644 app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadTask.java diff --git a/app/build.gradle b/app/build.gradle index b47ae972..08113599 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { applicationId "gr.thmmy.mthmmy" minSdkVersion 19 targetSdkVersion 28 - versionCode 21 - versionName "1.7.3" + versionCode 22 + versionName "1.7.4" archivesBaseName = "mTHMMY-v$versionName" buildConfigField "String", "CURRENT_BRANCH", "\"" + getCurrentBranch() + "\"" buildConfigField "String", "COMMIT_HASH", "\"" + getCommitHash() + "\"" diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java index 0b1195d2..98c23db9 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java @@ -40,7 +40,6 @@ import androidx.preference.PreferenceManager; import com.google.android.material.floatingactionbutton.FloatingActionButton; -import net.gotev.uploadservice.MultipartUploadRequest; import net.gotev.uploadservice.UploadNotificationAction; import net.gotev.uploadservice.UploadNotificationConfig; @@ -67,6 +66,7 @@ import gr.thmmy.mthmmy.services.UploadsReceiver; import gr.thmmy.mthmmy.utils.AppCompatSpinnerWithoutDefault; import gr.thmmy.mthmmy.utils.FileUtils; import gr.thmmy.mthmmy.utils.TakePhoto; +import gr.thmmy.mthmmy.activities.upload.multipart.MultipartUploadRequest; import gr.thmmy.mthmmy.utils.parsing.ParseException; import gr.thmmy.mthmmy.utils.parsing.ParseTask; import me.zhanghai.android.materialprogressbar.MaterialProgressBar; @@ -740,6 +740,7 @@ public class UploadActivity extends BaseActivity { .addFileToUpload(fileUri.toString() , "tp-dluploadfile") .addParameter("tp_dluploadicon", fileIcon) + .addParameter("tp_dluploadpic", "") .addParameter("tp-uploaduser", uploaderProfileIndex) .setNotificationConfig(uploadNotificationConfig) .setMaxRetries(2) diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadRequest.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadRequest.java new file mode 100644 index 00000000..f6126523 --- /dev/null +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadRequest.java @@ -0,0 +1,99 @@ +package gr.thmmy.mthmmy.activities.upload.multipart; + +import android.content.Context; +import android.content.Intent; + +import net.gotev.uploadservice.HttpUploadRequest; +import net.gotev.uploadservice.Logger; +import net.gotev.uploadservice.UploadFile; +import net.gotev.uploadservice.UploadTask; + +import java.io.FileNotFoundException; +import java.net.MalformedURLException; + +/** + From MultipartUploadRequest gotev/android-upload-service in order to use the local custom + MultipartUploadTask. + */ +public class MultipartUploadRequest extends HttpUploadRequest { + + private static final String LOG_TAG = MultipartUploadRequest.class.getSimpleName(); + private boolean isUtf8Charset = false; + + + public MultipartUploadRequest(final Context context, final String uploadId, final String serverUrl) + throws IllegalArgumentException, MalformedURLException { + super(context, uploadId, serverUrl); + } + + public MultipartUploadRequest(final Context context, final String serverUrl) + throws MalformedURLException, IllegalArgumentException { + this(context, null, serverUrl); + } + + @Override + protected void initializeIntent(Intent intent) { + super.initializeIntent(intent); + intent.putExtra(MultipartUploadTask.PARAM_UTF8_CHARSET, isUtf8Charset); + } + + @Override + protected Class getTaskClass() { + return MultipartUploadTask.class; + } + + public MultipartUploadRequest addFileToUpload(String filePath, + String parameterName, + String fileName, String contentType) + throws FileNotFoundException, IllegalArgumentException { + + UploadFile file = new UploadFile(filePath); + filePath = file.getPath(); + + if (parameterName == null || "".equals(parameterName)) { + throw new IllegalArgumentException("Please specify parameterName value for file: " + + filePath); + } + + file.setProperty(MultipartUploadTask.PROPERTY_PARAM_NAME, parameterName); + + if (contentType == null || contentType.isEmpty()) { + contentType = file.getContentType(context); + Logger.debug(LOG_TAG, "Auto-detected MIME type for " + filePath + + " is: " + contentType); + } else { + Logger.debug(LOG_TAG, "Content Type set for " + filePath + + " is: " + contentType); + } + + file.setProperty(MultipartUploadTask.PROPERTY_CONTENT_TYPE, contentType); + + if (fileName == null || "".equals(fileName)) { + fileName = file.getName(context); + Logger.debug(LOG_TAG, "Using original file name: " + fileName); + } else { + Logger.debug(LOG_TAG, "Using custom file name: " + fileName); + } + + file.setProperty(MultipartUploadTask.PROPERTY_REMOTE_FILE_NAME, fileName); + + params.files.add(file); + return this; + } + + public MultipartUploadRequest addFileToUpload(final String path, final String parameterName, + final String fileName) + throws FileNotFoundException, IllegalArgumentException { + return addFileToUpload(path, parameterName, fileName, null); + } + + public MultipartUploadRequest addFileToUpload(final String path, final String parameterName) + throws FileNotFoundException, IllegalArgumentException { + return addFileToUpload(path, parameterName, null, null); + } + + public MultipartUploadRequest setUtf8Charset() { + isUtf8Charset = true; + return this; + } +} \ No newline at end of file diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadTask.java new file mode 100644 index 00000000..be9bb0f6 --- /dev/null +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadTask.java @@ -0,0 +1,160 @@ +package gr.thmmy.mthmmy.activities.upload.multipart; + +import android.content.Intent; + +import net.gotev.uploadservice.HttpUploadTask; +import net.gotev.uploadservice.NameValue; +import net.gotev.uploadservice.UploadFile; +import net.gotev.uploadservice.UploadService; +import net.gotev.uploadservice.http.BodyWriter; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; + +/** + Extended MultipartUploadTask from gotev/android-upload-service to include a fix for the parameter + tp_dluploadpic. Also changed Connection to keep-alive. + */ +public class MultipartUploadTask extends HttpUploadTask { + + static final String PARAM_UTF8_CHARSET = "multipartUtf8Charset"; + + private static final String BOUNDARY_SIGNATURE = "-------AndroidUploadService"; + private static final Charset US_ASCII = Charset.forName("US-ASCII"); + private static final String NEW_LINE = "\r\n"; + private static final String TWO_HYPHENS = "--"; + + // properties associated to each file + static final String PROPERTY_REMOTE_FILE_NAME = "httpRemoteFileName"; + static final String PROPERTY_CONTENT_TYPE = "httpContentType"; + static final String PROPERTY_PARAM_NAME = "httpParamName"; + + private byte[] boundaryBytes; + private byte[] trailerBytes; + private Charset charset; + + @Override + protected void init(UploadService service, Intent intent) throws IOException { + super.init(service, intent); + + String boundary = BOUNDARY_SIGNATURE + System.nanoTime(); + boundaryBytes = (TWO_HYPHENS + boundary + NEW_LINE).getBytes(US_ASCII); + trailerBytes = (TWO_HYPHENS + boundary + TWO_HYPHENS + NEW_LINE).getBytes(US_ASCII); + charset = intent.getBooleanExtra(PARAM_UTF8_CHARSET, false) ? + Charset.forName("UTF-8") : US_ASCII; + + httpParams.addHeader("Connection", "Keep-Alive"); + httpParams.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary); + } + + @Override + protected long getBodyLength() throws UnsupportedEncodingException { + return (getRequestParametersLength() + getFilesLength() + trailerBytes.length); + } + + @Override + public void onBodyReady(BodyWriter bodyWriter) throws IOException { + //reset uploaded bytes when the body is ready to be written + //because sometimes this gets invoked when network changes + uploadedBytes = 0; + writeRequestParameters(bodyWriter); + writeFiles(bodyWriter); + bodyWriter.write(trailerBytes); + uploadedBytes += trailerBytes.length; + broadcastProgress(uploadedBytes, totalBytes); + } + + private long getFilesLength() throws UnsupportedEncodingException { + long total = 0; + + for (UploadFile file : params.files) { + total += getTotalMultipartBytes(file); + } + + return total; + } + + private long getRequestParametersLength() throws UnsupportedEncodingException { + long parametersBytes = 0; + + if (!httpParams.getRequestParameters().isEmpty()) { + for (final NameValue parameter : httpParams.getRequestParameters()) { + // the bytes needed for every parameter are the sum of the boundary bytes + // and the bytes occupied by the parameter + parametersBytes += boundaryBytes.length + getMultipartBytes(parameter).length; + } + } + + return parametersBytes; + } + + private byte[] getMultipartBytes(NameValue parameter) throws UnsupportedEncodingException { + if(parameter.getName().equals("tp_dluploadpic")){ + String header = "Content-Disposition: form-data; name=\"" + + parameter.getName() + "\"; filename=\"\"" + NEW_LINE + + "Content-Type: application/octet-stream" + NEW_LINE + NEW_LINE; + return header.getBytes(charset); + } + else + return ("Content-Disposition: form-data; name=\"" + parameter.getName() + "\"" + + NEW_LINE + NEW_LINE + parameter.getValue() + NEW_LINE).getBytes(charset); + } + + private byte[] getMultipartHeader(UploadFile file) + throws UnsupportedEncodingException { + String header = "Content-Disposition: form-data; name=\"" + + file.getProperty(PROPERTY_PARAM_NAME) + "\"; filename=\"" + + file.getProperty(PROPERTY_REMOTE_FILE_NAME) + "\"" + NEW_LINE + + "Content-Type: " + file.getProperty(PROPERTY_CONTENT_TYPE) + + NEW_LINE + NEW_LINE; + + return header.getBytes(charset); + } + + private long getTotalMultipartBytes(UploadFile file) + throws UnsupportedEncodingException { + return boundaryBytes.length + getMultipartHeader(file).length + file.length(service) + + NEW_LINE.getBytes(charset).length; + } + + private void writeRequestParameters(BodyWriter bodyWriter) throws IOException { + if (!httpParams.getRequestParameters().isEmpty()) { + for (final NameValue parameter : httpParams.getRequestParameters()) { + bodyWriter.write(boundaryBytes); + byte[] formItemBytes = getMultipartBytes(parameter); + bodyWriter.write(formItemBytes); + + uploadedBytes += boundaryBytes.length + formItemBytes.length; + broadcastProgress(uploadedBytes, totalBytes); + } + } + } + + private void writeFiles(BodyWriter bodyWriter) throws IOException { + for (UploadFile file : params.files) { + if (!shouldContinue) + break; + + bodyWriter.write(boundaryBytes); + byte[] headerBytes = getMultipartHeader(file); + bodyWriter.write(headerBytes); + + uploadedBytes += boundaryBytes.length + headerBytes.length; + broadcastProgress(uploadedBytes, totalBytes); + + bodyWriter.writeStream(file.getStream(service), this); + + byte[] newLineBytes = NEW_LINE.getBytes(charset); + bodyWriter.write(newLineBytes); + uploadedBytes += newLineBytes.length; + } + } + + @Override + protected void onSuccessfulUpload() { + addAllFilesToSuccessfullyUploadedFiles(); + } + +} + From d49651fdcc3acffab8fbe8c42f177e54c56d01a9 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Mon, 16 Sep 2019 20:01:24 +0300 Subject: [PATCH 06/10] Improved uploads error handling --- .../mthmmy/activities/upload/UploadActivity.java | 2 +- .../multipart/MultipartUploadException.java | 8 ++++++++ .../thmmy/mthmmy/services/UploadsReceiver.java | 16 +++++++++++++--- .../mthmmy/utils/parsing/ParseException.java | 5 ++--- 4 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadException.java diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java index 98c23db9..347acdc7 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java @@ -58,6 +58,7 @@ import java.util.Locale; import java.util.UUID; import gr.thmmy.mthmmy.R; +import gr.thmmy.mthmmy.activities.upload.multipart.MultipartUploadRequest; import gr.thmmy.mthmmy.base.BaseActivity; import gr.thmmy.mthmmy.base.BaseApplication; import gr.thmmy.mthmmy.model.UploadCategory; @@ -66,7 +67,6 @@ import gr.thmmy.mthmmy.services.UploadsReceiver; import gr.thmmy.mthmmy.utils.AppCompatSpinnerWithoutDefault; import gr.thmmy.mthmmy.utils.FileUtils; import gr.thmmy.mthmmy.utils.TakePhoto; -import gr.thmmy.mthmmy.activities.upload.multipart.MultipartUploadRequest; import gr.thmmy.mthmmy.utils.parsing.ParseException; import gr.thmmy.mthmmy.utils.parsing.ParseTask; import me.zhanghai.android.materialprogressbar.MaterialProgressBar; diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadException.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadException.java new file mode 100644 index 00000000..0b8cdc29 --- /dev/null +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/multipart/MultipartUploadException.java @@ -0,0 +1,8 @@ +package gr.thmmy.mthmmy.activities.upload.multipart; + +public class MultipartUploadException extends RuntimeException { + public MultipartUploadException(String message) { + super(message); + } + +} diff --git a/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java b/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java index f8b06e28..015dc91d 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java +++ b/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java @@ -22,8 +22,10 @@ import net.gotev.uploadservice.UploadServiceBroadcastReceiver; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.activities.upload.UploadsHelper; +import gr.thmmy.mthmmy.activities.upload.multipart.MultipartUploadException; import gr.thmmy.mthmmy.base.BaseApplication; import me.zhanghai.android.materialprogressbar.MaterialProgressBar; +import timber.log.Timber; public class UploadsReceiver extends UploadServiceBroadcastReceiver { public static final String UPLOAD_ID_KEY = "UPLOAD_ID_KEY"; @@ -153,7 +155,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { TextView dialogProgressText = progressWindow.findViewById(R.id.dialog_upload_progress_text); dialogProgressBar.setVisibility(View.GONE); - dialogProgressText.setText("Upload failed."); + dialogProgressText.setText("Upload failed"); } if (uploadInfo.getUploadedBytes() == uploadInfo.getTotalBytes()) { @@ -185,12 +187,20 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { dialogUploadID = null; } - Toast.makeText(context.getApplicationContext(), "Upload completed successfully", Toast.LENGTH_SHORT).show(); + String response = serverResponse.getBodyAsString(); + if(response.contains("Η προσθήκη του αρχείου ήταν επιτυχημένη.")||response.contains("The upload was successful.")){ + Toast.makeText(context.getApplicationContext(), "Upload completed successfully", Toast.LENGTH_SHORT).show(); + BaseApplication.getInstance().logFirebaseAnalyticsEvent("file_upload", null); + } + else { + Timber.e(new MultipartUploadException(response)); + onError(context,uploadInfo,serverResponse,new MultipartUploadException(response)); + } + if (storage == null) { storage = new Storage(context.getApplicationContext()); } - BaseApplication.getInstance().logFirebaseAnalyticsEvent("file_upload", null); UploadsHelper.deleteTempFiles(storage); } diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseException.java b/app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseException.java index 942e789b..5fc06664 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseException.java +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseException.java @@ -1,13 +1,12 @@ package gr.thmmy.mthmmy.utils.parsing; /** - * ParseException is to be used for errors while parsing. + * Use ParseException for errors while parsing. */ public class ParseException extends RuntimeException { public ParseException() {} - public ParseException(String message) - { + public ParseException(String message) { super(message); } From 0137f5b651e7908fcc2e9fa8726b77628f2933c2 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Mon, 16 Sep 2019 20:31:17 +0300 Subject: [PATCH 07/10] Minor uploads cleanup --- .../activities/upload/UploadActivity.java | 4 ++-- .../thmmy/mthmmy/services/UploadsReceiver.java | 17 +++++++++-------- app/src/main/res/values/strings.xml | 7 +++++-- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java index 347acdc7..dd728db4 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java @@ -710,13 +710,13 @@ public class UploadActivity extends BaseActivity { uploadNotificationConfig.getProgress().actions.add(new UploadNotificationAction( R.drawable.ic_cancel_accent_24dp, - context.getString(R.string.upload_notification_cancel), + context.getString(R.string.upload_cancel), PendingIntent.getBroadcast(context, 0, cancelIntent, PendingIntent.FLAG_UPDATE_CURRENT) )); uploadNotificationConfig.getError().actions.add(new UploadNotificationAction( R.drawable.ic_notification, - context.getString(R.string.upload_notification_retry), + context.getString(R.string.upload_retry), PendingIntent.getBroadcast(context, 0, retryIntent, PendingIntent.FLAG_UPDATE_CURRENT) )); diff --git a/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java b/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java index 015dc91d..6c978dda 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java +++ b/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java @@ -90,11 +90,11 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { uploadInfo.getUploadId().equals(dialogUploadID) && uploadProgressDialog != null) { Button alertDialogNeutral = uploadProgressDialog.getButton(AlertDialog.BUTTON_NEUTRAL); - alertDialogNeutral.setText("Resume on background"); + alertDialogNeutral.setText(R.string.upload_resume_in_background); alertDialogNeutral.setOnClickListener(v -> uploadProgressDialog.dismiss()); Button alertDialogNegative = uploadProgressDialog.getButton(AlertDialog.BUTTON_NEGATIVE); - alertDialogNegative.setText("Cancel"); + alertDialogNegative.setText(R.string.upload_cancel); alertDialogNegative.setOnClickListener(v -> { UploadService.stopUpload(dialogUploadID); uploadProgressDialog.dismiss(); @@ -137,7 +137,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { });*/ Button alertDialogNegative = uploadProgressDialog.getButton(AlertDialog.BUTTON_NEGATIVE); - alertDialogNegative.setText("Cancel"); + alertDialogNegative.setText(R.string.upload_cancel); alertDialogNegative.setOnClickListener(v -> { NotificationManager notificationManager = (NotificationManager) context.getApplicationContext(). getSystemService(Context.NOTIFICATION_SERVICE); @@ -155,7 +155,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { TextView dialogProgressText = progressWindow.findViewById(R.id.dialog_upload_progress_text); dialogProgressBar.setVisibility(View.GONE); - dialogProgressText.setText("Upload failed"); + dialogProgressText.setText(R.string.upload_failed); } if (uploadInfo.getUploadedBytes() == uploadInfo.getTotalBytes()) { @@ -174,7 +174,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { context.sendBroadcast(combinedActionsIntent); } - Toast.makeText(context.getApplicationContext(), "Upload failed", Toast.LENGTH_SHORT).show(); + Toast.makeText(context.getApplicationContext(), R.string.upload_failed, Toast.LENGTH_SHORT).show(); if (storage == null) { storage = new Storage(context.getApplicationContext()); } @@ -193,8 +193,9 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { BaseApplication.getInstance().logFirebaseAnalyticsEvent("file_upload", null); } else { - Timber.e(new MultipartUploadException(response)); - onError(context,uploadInfo,serverResponse,new MultipartUploadException(response)); + MultipartUploadException multipartUploadException = new MultipartUploadException(response); + Timber.e(multipartUploadException); + onError(context,uploadInfo,serverResponse,multipartUploadException); } if (storage == null) { @@ -211,7 +212,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { dialogUploadID = null; } - Toast.makeText(context.getApplicationContext(), "Upload canceled", Toast.LENGTH_SHORT).show(); + Toast.makeText(context.getApplicationContext(), R.string.upload_canceled, Toast.LENGTH_SHORT).show(); if (storage == null) { storage = new Storage(context.getApplicationContext()); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5d856f19..2a32d992 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -144,8 +144,11 @@ \nThis does not rename your local files. Uploading Uploading: %1$.2f Kbit/s, %2$d/%3$d KBytes - "Cancel" - "Retry" + "Upload failed" + "Upload canceled" + "Resume in background" + "Cancel" + "Retry" Select type of upload From 29c4caa7af680223cc00d2702af628fe7e78b721 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Tue, 17 Sep 2019 12:50:24 +0300 Subject: [PATCH 08/10] Up dependencies --- app/build.gradle | 16 ++++++++-------- build.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 08113599..a4f3e951 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,13 +6,14 @@ apply plugin: 'com.android.application' apply plugin: 'io.fabric' android { - compileSdkVersion 28 + compileSdkVersion 29 + buildToolsVersion = '29.0.2' defaultConfig { vectorDrawables.useSupportLibrary = true applicationId "gr.thmmy.mthmmy" minSdkVersion 19 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 22 versionName "1.7.4" archivesBaseName = "mTHMMY-v$versionName" @@ -71,15 +72,15 @@ tasks.whenTaskAdded { task -> dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'androidx.appcompat:appcompat:1.1.0-beta01' - implementation 'androidx.preference:preference:1.1.0-beta01' + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.preference:preference:1.1.0' implementation 'androidx.legacy:legacy-preference-v14:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.0.0' - implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-alpha01' + implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-alpha04' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation 'androidx.exifinterface:exifinterface:1.1.0-alpha01' + implementation 'androidx.exifinterface:exifinterface:1.1.0-beta01' implementation 'com.google.android.material:material:1.0.0' implementation 'com.google.firebase:firebase-core:17.0.0' implementation 'com.google.firebase:firebase-messaging:19.0.1' @@ -101,8 +102,7 @@ dependencies { implementation 'ru.noties:markwon:2.0.2' implementation 'net.gotev:uploadservice:3.5.2' implementation 'net.gotev:uploadservice-okhttp:3.4.2' //TODO: Warning: v.3.5 depends on okhttp 3.13! - implementation 'com.itkacher.okhttpprofiler:okhttpprofiler:1.0.5' -//Plugin: https://plugins.jetbrains.com/plugin/11249-okhttp-profiler + implementation 'com.itkacher.okhttpprofiler:okhttpprofiler:1.0.5' //Plugin: https://plugins.jetbrains.com/plugin/11249-okhttp-profiler } apply plugin: 'com.google.gms.google-services' diff --git a/build.gradle b/build.gradle index 65830711..70b74ad6 100644 --- a/build.gradle +++ b/build.gradle @@ -9,8 +9,8 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.4.1' - classpath 'com.google.gms:google-services:4.3.0' + classpath 'com.android.tools.build:gradle:3.5.0' + classpath 'com.google.gms:google-services:4.3.2' classpath 'io.fabric.tools:gradle:1.29.0' classpath 'org.ajoberstar.grgit:grgit-core:3.1.1' // Also change in app/gradle/grgit.gradle classpath "com.github.ben-manes:gradle-versions-plugin:0.21.0" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2e43564c..7076a01e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Jun 15 18:56:13 EEST 2019 +#Tue Sep 17 12:32:34 EEST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip From 2e0235de6140b77dd108f10440c358fc11ced0cb Mon Sep 17 00:00:00 2001 From: Ezerous Date: Tue, 17 Sep 2019 13:43:22 +0300 Subject: [PATCH 09/10] Fixes for fatal crashes --- .../main/recent/RecentFragment.java | 5 +-- .../main/unread/UnreadFragment.java | 7 ++-- .../mthmmy/activities/topic/Posting.java | 35 ++++++++++--------- .../activities/topic/TopicActivity.java | 4 +-- ...ForReply.java => PrepareForReplyTask.java} | 16 +++++---- .../mthmmy/viewmodel/TopicViewModel.java | 12 +++---- 6 files changed, 44 insertions(+), 35 deletions(-) rename app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/{PrepareForReply.java => PrepareForReplyTask.java} (83%) diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java index 4f4517d1..6e14b79b 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java @@ -22,6 +22,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import gr.thmmy.mthmmy.R; +import gr.thmmy.mthmmy.base.BaseApplication; import gr.thmmy.mthmmy.base.BaseFragment; import gr.thmmy.mthmmy.model.TopicSummary; import gr.thmmy.mthmmy.session.SessionManager; @@ -146,9 +147,9 @@ public class RecentFragment extends BaseFragment { topicSummaries.addAll(fetchedRecent); recentAdapter.notifyDataSetChanged(); } else if (resultCode == NetworkResultCodes.NETWORK_ERROR) { - Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show(); + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Network error", Toast.LENGTH_SHORT).show(); } else { - Toast.makeText(getContext(), "Unexpected error," + + Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Unexpected error," + " please contact the developers with the details", Toast.LENGTH_LONG).show(); } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java index cec14e97..1db4131e 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java @@ -143,11 +143,12 @@ public class UnreadFragment extends BaseFragment { @Override public void onDestroy() { super.onDestroy(); - if (unreadTask.isRunning()) + if (unreadTask!=null && unreadTask.isRunning()) unreadTask.cancel(true); - if (markReadTask.isRunning()) + if (markReadTask!=null && markReadTask.isRunning()) markReadTask.cancel(true); - topicSummaries.clear(); + if(topicSummaries!=null) + topicSummaries.clear(); } public interface UnreadFragmentInteractionListener extends FragmentInteractionListener { diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/Posting.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/Posting.java index 88c2f8a3..6fb1cc3f 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/Posting.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/Posting.java @@ -2,6 +2,7 @@ package gr.thmmy.mthmmy.activities.topic; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; import java.io.IOException; @@ -60,22 +61,24 @@ public class Posting { String finalUrl = response.request().url().toString(); if (finalUrl.contains("action=post")) { Document postErrorPage = Jsoup.parse(response.body().string()); - String[] errors = postErrorPage.select("tr[id=errors] div[id=error_list]").first() - .toString().split("
"); - for (int i = 0; i < errors.length; ++i) { //TODO test - Timber.d(String.valueOf(i)); - Timber.d(errors[i]); - } - for (String error : errors) { - if (error.contains("Your session timed out while posting") || - error.contains("Υπερβήκατε τον μέγιστο χρόνο σύνδεσης κατά την αποστολή")) - return REPLY_STATUS.SESSION_ENDED; - if (error.contains("No subject was filled in") - || error.contains("Δεν δόθηκε τίτλος")) - return REPLY_STATUS.NO_SUBJECT; - if (error.contains("The message body was left empty") - || error.contains("Δεν δόθηκε κείμενο για το μήνυμα")) - return REPLY_STATUS.EMPTY_BODY; + Element errorsElement = postErrorPage.select("tr[id=errors] div[id=error_list]").first(); + if(errorsElement!=null){ + String[] errors = errorsElement.toString().split("
"); + for (int i = 0; i < errors.length; ++i) { //TODO test + Timber.d(String.valueOf(i)); + Timber.d(errors[i]); + } + for (String error : errors) { + if (error.contains("Your session timed out while posting") || + error.contains("Υπερβήκατε τον μέγιστο χρόνο σύνδεσης κατά την αποστολή")) + return REPLY_STATUS.SESSION_ENDED; + if (error.contains("No subject was filled in") + || error.contains("Δεν δόθηκε τίτλος")) + return REPLY_STATUS.NO_SUBJECT; + if (error.contains("The message body was left empty") + || error.contains("Δεν δόθηκε κείμενο για το μήνυμα")) + return REPLY_STATUS.EMPTY_BODY; + } } return REPLY_STATUS.NEW_REPLY_WHILE_POSTING; } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java index d3d97663..e0e52b3e 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java @@ -42,7 +42,7 @@ import java.util.ArrayList; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.activities.topic.tasks.EditTask; import gr.thmmy.mthmmy.activities.topic.tasks.PrepareForEditTask; -import gr.thmmy.mthmmy.activities.topic.tasks.PrepareForReply; +import gr.thmmy.mthmmy.activities.topic.tasks.PrepareForReplyTask; import gr.thmmy.mthmmy.activities.topic.tasks.ReplyTask; import gr.thmmy.mthmmy.activities.topic.tasks.TopicTask; import gr.thmmy.mthmmy.base.BaseActivity; @@ -618,7 +618,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo } } }); - viewModel.setPrepareForReplyCallbacks(new PrepareForReply.PrepareForReplyCallbacks() { + viewModel.setPrepareForReplyCallbacks(new PrepareForReplyTask.PrepareForReplyCallbacks() { @Override public void onPrepareForReplyStarted() { progressBar.setVisibility(ProgressBar.VISIBLE); diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReply.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReplyTask.java similarity index 83% rename from app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReply.java rename to app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReplyTask.java index bf5e12e0..36024a7e 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReply.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReplyTask.java @@ -15,13 +15,13 @@ import okhttp3.Request; import okhttp3.Response; import timber.log.Timber; -public class PrepareForReply extends AsyncTask { +public class PrepareForReplyTask extends AsyncTask { private PrepareForReplyCallbacks listener; private OnPrepareForReplyFinished finishListener; private String replyPageUrl; - public PrepareForReply(PrepareForReplyCallbacks listener, OnPrepareForReplyFinished finishListener, - String replyPageUrl) { + public PrepareForReplyTask(PrepareForReplyCallbacks listener, OnPrepareForReplyFinished finishListener, + String replyPageUrl) { this.listener = listener; this.finishListener = finishListener; this.replyPageUrl = replyPageUrl; @@ -49,12 +49,16 @@ public class PrepareForReply extends AsyncTask voteTaskFinishedListener; private ExternalAsyncTask.OnTaskStartedListener removeVoteTaskStartedListener; @@ -177,7 +177,7 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa stopLoading(); setPageIndicatorIndex(pageCount, true); Timber.i("Preparing for reply"); - currentPrepareForReplyTask = new PrepareForReply(prepareForReplyCallbacks, this, + currentPrepareForReplyTask = new PrepareForReplyTask(prepareForReplyCallbacks, this, replyPageUrl.getValue()); currentPrepareForReplyTask.execute(toQuoteList.toArray(new Integer[0])); } @@ -424,7 +424,7 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa this.editTaskCallbacks = editTaskCallbacks; } - public void setPrepareForReplyCallbacks(PrepareForReply.PrepareForReplyCallbacks prepareForReplyCallbacks) { + public void setPrepareForReplyCallbacks(PrepareForReplyTask.PrepareForReplyCallbacks prepareForReplyCallbacks) { this.prepareForReplyCallbacks = prepareForReplyCallbacks; } From a6a3280aa80366ce443e3988ea8186c4e34ded21 Mon Sep 17 00:00:00 2001 From: Ezerous Date: Tue, 17 Sep 2019 18:58:16 +0300 Subject: [PATCH 10/10] Uploads minor tweaks --- .../activities/upload/UploadActivity.java | 20 ++++----- .../gr/thmmy/mthmmy/base/BaseActivity.java | 10 ++--- .../mthmmy/services/UploadsReceiver.java | 41 +++++++++---------- .../mthmmy/viewmodel/TopicViewModel.java | 2 +- app/src/main/res/values/strings.xml | 5 +-- 5 files changed, 38 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java index dd728db4..0d9135a4 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java @@ -372,7 +372,6 @@ public class UploadActivity extends BaseActivity { requestPerms(UPLOAD_REQUEST_STORAGE_CODE); dialog.cancel(); } - return; } @@ -667,7 +666,7 @@ public class UploadActivity extends BaseActivity { filesListView.setVisibility(View.VISIBLE); } - public static UploadNotificationConfig getConfigForUpload(Context context, String uploadID, + public UploadNotificationConfig getConfigForUpload(Context context, String uploadID, String filename) { UploadNotificationConfig uploadNotificationConfig = new UploadNotificationConfig(); uploadNotificationConfig.setIconForAllStatuses(android.R.drawable.stat_sys_upload); @@ -699,7 +698,7 @@ public class UploadActivity extends BaseActivity { uploadNotificationConfig.setClickIntentForAllStatuses(PendingIntent.getBroadcast(context, 1, combinedActionsIntent, PendingIntent.FLAG_UPDATE_CURRENT)); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + else { Intent retryIntent = new Intent(context, UploadsReceiver.class); retryIntent.setAction(UploadsReceiver.ACTION_RETRY_UPLOAD); retryIntent.putExtra(UploadsReceiver.UPLOAD_ID_KEY, uploadID); @@ -710,7 +709,7 @@ public class UploadActivity extends BaseActivity { uploadNotificationConfig.getProgress().actions.add(new UploadNotificationAction( R.drawable.ic_cancel_accent_24dp, - context.getString(R.string.upload_cancel), + context.getString(R.string.cancel), PendingIntent.getBroadcast(context, 0, cancelIntent, PendingIntent.FLAG_UPDATE_CURRENT) )); @@ -731,7 +730,7 @@ public class UploadActivity extends BaseActivity { String uploadDescriptionText, String fileIcon, String uploaderProfileIndex, Uri fileUri) { try { - new MultipartUploadRequest(context, uploadID, uploadIndexUrl) + MultipartUploadRequest multipartUploadRequest = new MultipartUploadRequest(context, uploadID, uploadIndexUrl) .setUtf8Charset() .setNotificationConfig(uploadNotificationConfig) .addParameter("tp-dluploadtitle", uploadTitleText) @@ -743,10 +742,11 @@ public class UploadActivity extends BaseActivity { .addParameter("tp_dluploadpic", "") .addParameter("tp-uploaduser", uploaderProfileIndex) .setNotificationConfig(uploadNotificationConfig) - .setMaxRetries(2) - .startUpload(); - - Toast.makeText(context, "Uploading files in the background.", Toast.LENGTH_SHORT).show(); + .setMaxRetries(2); + Timber.d("Uploading a file with properties: \nTitle: %s\nCategory: %s\nDescription: %s\nIcon: %s\nUploader: %s", + uploadTitleText, categorySelected, uploadDescriptionText, fileIcon, uploaderProfileIndex); + multipartUploadRequest.startUpload(); + Toast.makeText(context, "Uploading file(s) in the background...", Toast.LENGTH_SHORT).show(); return true; } catch (Exception exception) { Timber.e(exception, "AndroidUploadService: %s", exception.getMessage()); @@ -1006,7 +1006,7 @@ public class UploadActivity extends BaseActivity { } } - public static class ZipTask extends AsyncTask { + public class ZipTask extends AsyncTask { // Weak references will still allow the Activity to be garbage-collected private final WeakReference weakActivity; final String zipFilename, categorySelected, uploadTitleText, uploadDescriptionText, diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java index 0671b7e3..a4ea57dd 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java @@ -921,22 +921,22 @@ public abstract class BaseActivity extends AppCompatActivity { progressDialogBuilder.setView(progressDialogLayout); uploadsProgressDialog = progressDialogBuilder.create(); - if (!UploadService.getTaskList().contains("" + dialogUploadID)) { + if (!UploadService.getTaskList().contains(dialogUploadID)) { //Upload probably failed at this point - uploadsProgressDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "Retry", (progressDialog, progressWhich) -> { + uploadsProgressDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "", (progressDialog, progressWhich) -> { /*LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context.getApplicationContext()); localBroadcastManager.sendBroadcast(multipartUploadRetryIntent);*/ - uploadsProgressDialog.dismiss(); + //uploadsProgressDialog.dismiss(); //context.sendBroadcast(retryIntent); }); - uploadsProgressDialog.setButton(AlertDialog.BUTTON_NEGATIVE, "Cancel", (progressDialog, progressWhich) -> { + uploadsProgressDialog.setButton(AlertDialog.BUTTON_NEGATIVE, getString(R.string.cancel), (progressDialog, progressWhich) -> { uploadsProgressDialog.dismiss(); }); TextView dialogProgressText = progressDialogLayout.findViewById(R.id.dialog_upload_progress_text); dialogProgressBar.setVisibility(View.GONE); - dialogProgressText.setText("Upload failed."); + dialogProgressText.setText(getString(R.string.upload_failed)); uploadsProgressDialog.show(); } else { diff --git a/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java b/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java index 6c978dda..1406eb57 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java +++ b/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java @@ -59,6 +59,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { switch (intentAction) { case ACTION_CANCEL_UPLOAD: String uploadID = intentBundle.getString(UPLOAD_ID_KEY); + Timber.d("Received ACTION_CANCEL_UPLOAD (id: %s)", uploadID); UploadService.stopUpload(uploadID); break; /*case ACTION_RETRY_UPLOAD: @@ -86,6 +87,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { @Override public void onProgress(Context context, UploadInfo uploadInfo) { + Timber.i("Upload in progress (id: %s)",uploadInfo.getUploadId()); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && uploadInfo.getUploadId().equals(dialogUploadID) && uploadProgressDialog != null) { @@ -94,8 +96,9 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { alertDialogNeutral.setOnClickListener(v -> uploadProgressDialog.dismiss()); Button alertDialogNegative = uploadProgressDialog.getButton(AlertDialog.BUTTON_NEGATIVE); - alertDialogNegative.setText(R.string.upload_cancel); + alertDialogNegative.setText(R.string.cancel); alertDialogNegative.setOnClickListener(v -> { + Timber.d("Cancelling upload (id: %s)", dialogUploadID); UploadService.stopUpload(dialogUploadID); uploadProgressDialog.dismiss(); }); @@ -124,6 +127,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { @Override public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse, Exception exception) { + Timber.i("Error while uploading (id: %s)",uploadInfo.getUploadId()); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && uploadInfo.getUploadId().equals(dialogUploadID) && uploadProgressDialog != null) { @@ -137,13 +141,9 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { });*/ Button alertDialogNegative = uploadProgressDialog.getButton(AlertDialog.BUTTON_NEGATIVE); - alertDialogNegative.setText(R.string.upload_cancel); + alertDialogNegative.setText(R.string.cancel); alertDialogNegative.setOnClickListener(v -> { - NotificationManager notificationManager = (NotificationManager) context.getApplicationContext(). - getSystemService(Context.NOTIFICATION_SERVICE); - if (notificationManager != null) { - notificationManager.cancel(uploadInfo.getNotificationID()); - } + cancelNotification(context, uploadInfo.getNotificationID()); UploadsHelper.deleteTempFiles(storage); uploadProgressDialog.dismiss(); }); @@ -163,12 +163,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { } } } else { - NotificationManager notificationManager = (NotificationManager) context.getApplicationContext(). - getSystemService(Context.NOTIFICATION_SERVICE); - if (notificationManager != null) { - notificationManager.cancel(uploadInfo.getNotificationID()); - } - + cancelNotification(context, uploadInfo.getNotificationID()); Intent combinedActionsIntent = new Intent(UploadsReceiver.ACTION_COMBINED_UPLOAD); combinedActionsIntent.putExtra(UploadsReceiver.UPLOAD_ID_KEY, uploadInfo.getUploadId()); context.sendBroadcast(combinedActionsIntent); @@ -189,6 +184,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { String response = serverResponse.getBodyAsString(); if(response.contains("Η προσθήκη του αρχείου ήταν επιτυχημένη.")||response.contains("The upload was successful.")){ + Timber.i("Upload completed successfully (id: %s)",uploadInfo.getUploadId()); Toast.makeText(context.getApplicationContext(), "Upload completed successfully", Toast.LENGTH_SHORT).show(); BaseApplication.getInstance().logFirebaseAnalyticsEvent("file_upload", null); } @@ -207,21 +203,17 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { @Override public void onCancelled(Context context, UploadInfo uploadInfo) { + Timber.i("Upload cancelled (id: %s)", uploadInfo.getUploadId()); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { uploadProgressDialog = null; dialogUploadID = null; } - Toast.makeText(context.getApplicationContext(), R.string.upload_canceled, Toast.LENGTH_SHORT).show(); - if (storage == null) { + Toast.makeText(context.getApplicationContext(), R.string.upload_cancelled, Toast.LENGTH_SHORT).show(); + if (storage == null) storage = new Storage(context.getApplicationContext()); - } - /*NotificationManager notificationManager = (NotificationManager) context.getApplicationContext(). - getSystemService(Context.NOTIFICATION_SERVICE); - if (notificationManager != null) { - notificationManager.cancel(uploadInfo.getNotificationID()); - }*/ + //cancelNotification(context, uploadInfo.getNotificationID()); UploadsHelper.deleteTempFiles(storage); } @@ -231,4 +223,11 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver { UploadsReceiver.dialogUploadID = dialogUploadID; //UploadsReceiver.multipartUploadRetryIntent = multipartUploadRetryIntent; } + + private void cancelNotification(Context context, int notificationId){ + NotificationManager notificationManager = (NotificationManager) context.getApplicationContext(). + getSystemService(Context.NOTIFICATION_SERVICE); + if (notificationManager != null) + notificationManager.cancel(notificationId); + } } \ No newline at end of file diff --git a/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java b/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java index 6c23115e..bac3952a 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java +++ b/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java @@ -17,8 +17,8 @@ import gr.thmmy.mthmmy.activities.topic.tasks.DeleteTask; import gr.thmmy.mthmmy.activities.topic.tasks.EditTask; import gr.thmmy.mthmmy.activities.topic.tasks.PrepareForEditResult; import gr.thmmy.mthmmy.activities.topic.tasks.PrepareForEditTask; -import gr.thmmy.mthmmy.activities.topic.tasks.PrepareForReplyTask; import gr.thmmy.mthmmy.activities.topic.tasks.PrepareForReplyResult; +import gr.thmmy.mthmmy.activities.topic.tasks.PrepareForReplyTask; import gr.thmmy.mthmmy.activities.topic.tasks.RemoveVoteTask; import gr.thmmy.mthmmy.activities.topic.tasks.ReplyTask; import gr.thmmy.mthmmy.activities.topic.tasks.SubmitVoteTask; diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2a32d992..fabd3e8a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -13,7 +13,7 @@ Bookmarks Info OK - Cancel + "Cancel" "To use mTHMMY you have to agree to our Privacy Policy by choosing one of the options below. Choose \"Yes, I want to help\", if you consent to the collection of anonymized data that will help us improve the app. Otherwise, choose \"Nope, leave me alone\". You can change your preferences any time through the app's Settings. user_consent_shared_preference_key @@ -145,9 +145,8 @@ Uploading Uploading: %1$.2f Kbit/s, %2$d/%3$d KBytes "Upload failed" - "Upload canceled" + "Upload canceled" "Resume in background" - "Cancel" "Retry"