diff --git a/app/build.gradle b/app/build.gradle
index 29faec1f..6171590a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -7,15 +7,15 @@ apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
android {
- compileSdkVersion 30
+ compileSdkVersion 31
buildToolsVersion = '30.0.2'
defaultConfig {
applicationId "gr.thmmy.mthmmy"
minSdkVersion 21
targetSdkVersion 30
- versionCode 30
- versionName "2.0.0"
+ versionCode 31
+ versionName "2.0.1"
archivesBaseName = "mTHMMY-v$versionName"
buildConfigField "String", "CURRENT_BRANCH", "\"" + getCurrentBranch() + "\""
buildConfigField "String", "COMMIT_HASH", "\"" + getCommitHash() + "\""
@@ -76,14 +76,14 @@ tasks.whenTaskAdded { task ->
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(":emojis")
- implementation 'androidx.appcompat:appcompat:1.4.0-alpha03'
+ implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'androidx.preference:preference:1.1.1'
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.2.1'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
- implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.exifinterface:exifinterface:1.3.3'
implementation 'com.google.android.material:material:1.4.0'
implementation platform('com.google.firebase:firebase-bom:28.4.0')
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9003cab6..7c7d5b18 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -7,8 +7,8 @@
-
+
@@ -41,6 +41,7 @@
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTask"
+ android:exported="true"
android:theme="@style/AppTheme.NoActionBar">
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 e0b5b986..48ec3b5b 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
@@ -10,6 +10,7 @@ import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.Spannable;
@@ -327,30 +328,20 @@ public class UploadActivity extends BaseActivity {
//File should be uploaded with a different name
if (checkPerms()) {
- if (!uploadFile.isCameraPhoto()) {
- //Temporarily copies the file to a another location and renames it
- tempFileUri = UploadsHelper.createTempFile(this, storage,
- uploadFile.getFileUri(),
- FileUtils.getFilenameWithoutExtension(editTextFilename));
- }
- else {
- //Renames the photo taken
- String photoPath = uploadFile.getPhotoFile().getPath();
- photoPath = photoPath.substring(0, photoPath.lastIndexOf(File.separator));
- String destinationFilename = photoPath + File.separator +
- FileUtils.getFilenameWithoutExtension(editTextFilename) + ".jpg";
-
- if (!storage.rename(uploadFile.getPhotoFile().getAbsolutePath(), destinationFilename)) {
- //Something went wrong, abort
- Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Could not create temporary file for renaming", Toast.LENGTH_SHORT).show();
- progressBar.setVisibility(View.GONE);
- return;
- }
-
- //Points photoFile and fileUri to the new copied and renamed file
- uploadFile.setPhotoFile(storage.getFile(destinationFilename));
- uploadFile.setFileUri(FileProvider.getUriForFile(this, getPackageName() +
- ".provider", uploadFile.getPhotoFile()));
+ String newFileName = FileUtils.getFilenameWithoutExtension(editTextFilename);
+
+ if(uploadFile.isCameraPhoto())
+ newFileName = newFileName + ".jpg";
+
+ //Temporarily copies the file to another location (external cache) and renames it
+ tempFileUri = UploadsHelper.createTempFile(this, storage,
+ uploadFile.getFileUri(),
+ newFileName);
+
+ //Something went wrong while creating temporary file, abort
+ if(tempFileUri == null){
+ progressBar.setVisibility(View.GONE);
+ return;
}
}
else {
@@ -561,7 +552,7 @@ public class UploadActivity extends BaseActivity {
UploadFile newFile = new UploadFile(true, TakePhoto.processResult(this,
photoFileCreated), photoFileCreated);
addFileViewToList(FileUtils.getFilenameWithoutExtension(FileUtils.
- filenameFromUri(this, newFile.getFileUri())));
+ filenameFromUri(this, newFile.getFileUri())) + ".jpg");
filesList.add(newFile);
}
else if (requestCode == AFR_REQUEST_CODE_FIELDS_BUILDER) {
@@ -596,6 +587,10 @@ public class UploadActivity extends BaseActivity {
case UPLOAD_REQUEST_CAMERA_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
takePhoto();
+ else {
+ Timber.w("Take photo failed (permission denied).");
+ Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Take photo failed (storage permission denied)", Toast.LENGTH_SHORT).show();
+ }
break;
case UPLOAD_REQUEST_STORAGE_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED &&
@@ -609,6 +604,7 @@ public class UploadActivity extends BaseActivity {
finish();
}
else {
+ Timber.w("Zip task failed (permission denied).");
Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Please retry uploading.", Toast.LENGTH_SHORT).show();
}
break;
@@ -720,17 +716,23 @@ public class UploadActivity extends BaseActivity {
cancelIntent.setAction(UploadsReceiver.ACTION_CANCEL_UPLOAD);
cancelIntent.putExtra(UploadsReceiver.UPLOAD_ID_KEY, uploadID);
+ int pendingIntentFlags;
+ if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
+ pendingIntentFlags = PendingIntent.FLAG_MUTABLE |PendingIntent.FLAG_UPDATE_CURRENT;
+ else
+ pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT;
+
uploadNotificationConfig.getProgress().actions.add(new UploadNotificationAction(
R.drawable.ic_cancel_accent_24dp,
context.getString(R.string.cancel),
PendingIntent.getBroadcast(context, 0, cancelIntent,
- PendingIntent.FLAG_UPDATE_CURRENT)
+ pendingIntentFlags)
));
uploadNotificationConfig.getError().actions.add(new UploadNotificationAction(
R.drawable.ic_notification,
context.getString(R.string.upload_retry),
PendingIntent.getBroadcast(context, 0, retryIntent,
- PendingIntent.FLAG_UPDATE_CURRENT)
+ pendingIntentFlags)
));
return uploadNotificationConfig;
@@ -1069,7 +1071,7 @@ public class UploadActivity extends BaseActivity {
@Override
protected void onPreExecute() {
assert weakActivity != null;
- Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Zipping files", Toast.LENGTH_SHORT).show();
+ Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Zipping files...", Toast.LENGTH_SHORT).show();
}
@Override
@@ -1077,7 +1079,7 @@ public class UploadActivity extends BaseActivity {
if (weakActivity == null || zipFilename == null)
return false;
- File zipFile = UploadsHelper.createZipFile(zipFilename);
+ File zipFile = UploadsHelper.createZipFile(weakActivity.get(), zipFilename);
if (zipFile == null)
return false;
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java
index 73b7fd21..af91d72c 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java
@@ -2,7 +2,6 @@ package gr.thmmy.mthmmy.activities.upload;
import android.content.Context;
import android.net.Uri;
-import android.os.Environment;
import android.widget.Toast;
import androidx.annotation.NonNull;
@@ -27,24 +26,19 @@ import timber.log.Timber;
public class UploadsHelper {
private static final int BUFFER = 4096;
- private static final String TEMP_FILES_DIRECTORY = "~tmp_mTHMMY_uploads";
@SuppressWarnings("ResultOfMethodCallIgnored")
@Nullable
static Uri createTempFile(Context context, Storage storage, Uri fileUri, String newFilename) {
+ Timber.i("Creating new temporary file (%s)", newFilename);
String oldFilename = FileUtils.filenameFromUri(context, fileUri);
String fileExtension = oldFilename.substring(oldFilename.indexOf('.'));
- String destinationFilename = Environment.getExternalStorageDirectory().getPath() +
- File.separatorChar + TEMP_FILES_DIRECTORY + File.separatorChar + newFilename + fileExtension;
- File tempDirectory = new File(android.os.Environment.getExternalStorageDirectory().getPath() +
- File.separatorChar + TEMP_FILES_DIRECTORY);
-
- if (!tempDirectory.exists() && !tempDirectory.mkdirs()) {
- Timber.w("Temporary directory build returned false in %s", UploadActivity.class.getSimpleName());
- Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Couldn't create temporary directory", Toast.LENGTH_SHORT).show();
+ File tempFilesDirectory = createTempFilesDir(context);
+ if (tempFilesDirectory==null)
return null;
- }
+
+ String destinationFilename = tempFilesDirectory.getAbsolutePath() + File.separatorChar + newFilename + fileExtension;
InputStream inputStream;
BufferedInputStream bufferedInputStream = null;
@@ -53,7 +47,7 @@ public class UploadsHelper {
try {
inputStream = context.getContentResolver().openInputStream(fileUri);
if (inputStream == null) {
- Timber.w("Input stream was null, %s", UploadActivity.class.getSimpleName());
+ Timber.e("Input stream was null, %s", UploadActivity.class.getSimpleName());
return null;
}
@@ -81,20 +75,19 @@ public class UploadsHelper {
}
@Nullable
- static File createZipFile(@NonNull String zipFilename) {
- // Create a zip file name
- File zipFolder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) +
- File.separator + "mTHMMY");
+ static File createZipFile(Context context, @NonNull String zipFilename) {
+ // Create a zip file in temp directory
+ Timber.i("Creating temporary zip file %s", zipFilename);
- if (!zipFolder.exists() && !zipFolder.mkdirs()) {
- Timber.w("Zip folder build returned false in %s", UploadsHelper.class.getSimpleName());
+ File tempFilesDirectory = createTempFilesDir(context);
+ if (tempFilesDirectory==null)
return null;
- }
- return new File(zipFolder, zipFilename);
+ return new File(tempFilesDirectory, zipFilename);
}
static void zip(Context context, Uri[] files, Uri zipFile) {
+ Timber.i("Adding files to %s...", zipFile.getPath());
try {
BufferedInputStream origin;
OutputStream dest = context.getContentResolver().openOutputStream(zipFile);
@@ -117,21 +110,45 @@ public class UploadsHelper {
origin.close();
}
+ Timber.i("Files added successfully to %s.", zipFile.getPath());
+
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
- public static void deleteTempFiles(Storage storage) {
- File tempFilesDirectory = new File(Environment.getExternalStorageDirectory().getPath() +
- File.separatorChar + TEMP_FILES_DIRECTORY);
+ private static File createTempFilesDir(Context context){
+ File tempFilesDirectory = context.getExternalCacheDir();
+
+ if (tempFilesDirectory == null){
+ Timber.e("Temporary files directory error (%s)!", UploadActivity.class.getSimpleName());
+ Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Temporary files directory error (%s)!", Toast.LENGTH_SHORT).show();
+ return null;
+ }
- if (storage.isDirectoryExists(tempFilesDirectory.getAbsolutePath())) {
- for (File tempFile : storage.getFiles(tempFilesDirectory.getAbsolutePath())) {
- storage.deleteFile(tempFile.getAbsolutePath());
+ if (!tempFilesDirectory.exists() && !tempFilesDirectory.mkdirs()) {
+ Timber.e("Temporary directory %s creation returned false (%s)", tempFilesDirectory.getAbsolutePath(), UploadActivity.class.getSimpleName());
+ Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Couldn't create temporary directory for file renaming!", Toast.LENGTH_SHORT).show();
+ return null;
+ }
+
+ return tempFilesDirectory;
+ }
+
+ public static void deleteTempFiles(Context context, Storage storage) {
+ File tempFilesDirectory = context.getExternalCacheDir();
+
+ if (tempFilesDirectory != null){
+ if (storage.isDirectoryExists(tempFilesDirectory.getAbsolutePath())) {
+ for (File tempFile : storage.getFiles(tempFilesDirectory.getAbsolutePath())) {
+ storage.deleteFile(tempFile.getAbsolutePath());
+ }
+ storage.deleteDirectory(tempFilesDirectory.getAbsolutePath());
+ Timber.i("Deleted temp files from cache.");
}
- storage.deleteDirectory(tempFilesDirectory.getAbsolutePath());
}
+ else
+ Timber.e("Couldn't delete temp files!");
}
}
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 f2af6b7e..21e1af95 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
@@ -694,6 +694,7 @@ public abstract class BaseActivity extends AppCompatActivity {
//True if permissions are OK
protected boolean checkPerms() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
+ Timber.i("Checking storage permissions.");
String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
@@ -705,12 +706,14 @@ public abstract class BaseActivity extends AppCompatActivity {
}
//Display popup for user to grant permission
- protected void requestPerms(int code) { //Runtime permissions request for devices with API >= 23
+ protected void requestPerms(int code) {
+ //Runtime permissions request for devices with API >= 23
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
+ Timber.i("Requesting storage permissions (code %d).", code);
requestPermissions(PERMISSIONS_STORAGE, code);
}
}
@@ -722,10 +725,13 @@ public abstract class BaseActivity extends AppCompatActivity {
if (permsRequestCode == DOWNLOAD_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
prepareDownload(tempThmmyFile);
+ else {
+ Timber.w("Download failed (permission denied).");
+ Toast.makeText(BaseApplication.getInstance().getApplicationContext(), "Download failed (storage permission denied)", Toast.LENGTH_SHORT).show();
+ }
}
}
-
//----------------------------------DOWNLOAD----------------------
private ThmmyFile tempThmmyFile;
diff --git a/app/src/main/java/gr/thmmy/mthmmy/services/NotificationService.java b/app/src/main/java/gr/thmmy/mthmmy/services/NotificationService.java
index b271e39f..482dffdb 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/services/NotificationService.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/services/NotificationService.java
@@ -178,8 +178,15 @@ public class NotificationService extends FirebaseMessagingService {
extras.putString(BUNDLE_TOPIC_TITLE, postNotification.getTopicTitle());
intent.putExtras(extras);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+
+ int pendingIntentFlags;
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S)
+ pendingIntentFlags = PendingIntent.FLAG_IMMUTABLE |PendingIntent.FLAG_ONE_SHOT;
+ else
+ pendingIntentFlags = PendingIntent.FLAG_ONE_SHOT;
+
PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode++, intent,
- PendingIntent.FLAG_ONE_SHOT);
+ pendingIntentFlags);
int notificationId;
String contentText;
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 9823d3d3..19c52396 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/services/UploadsReceiver.java
@@ -105,7 +105,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();
+ Toast.makeText(context.getApplicationContext(), "Upload completed successfully!", Toast.LENGTH_SHORT).show();
BaseApplication.getInstance().logFirebaseAnalyticsEvent("file_upload", null);
}
else {
@@ -118,7 +118,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver {
storage = new Storage(context.getApplicationContext());
}
- UploadsHelper.deleteTempFiles(storage);
+ UploadsHelper.deleteTempFiles(context, storage);
}
@Override
@@ -130,7 +130,7 @@ public class UploadsReceiver extends UploadServiceBroadcastReceiver {
storage = new Storage(context.getApplicationContext());
//cancelNotification(context, uploadInfo.getNotificationID());
- UploadsHelper.deleteTempFiles(storage);
+ UploadsHelper.deleteTempFiles(context, storage);
}
public static void setDialogDisplay(AlertDialog uploadProgressDialog, String dialogUploadID,
diff --git a/app/src/main/res/layout/activity_upload_file_list_row.xml b/app/src/main/res/layout/activity_upload_file_list_row.xml
index 08b74a4a..8af02800 100644
--- a/app/src/main/res/layout/activity_upload_file_list_row.xml
+++ b/app/src/main/res/layout/activity_upload_file_list_row.xml
@@ -3,7 +3,9 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:paddingStart="8dp"
+ android:paddingEnd="0dp">