Browse Source

Rename file when generator is used, Keep only successfully uploaded taken photos, Add library for file management, Add file size check

uploads
Apostolos Fanakis 6 years ago
parent
commit
76ce86dfce
  1. 1
      app/build.gradle
  2. 118
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java
  3. 70
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java
  4. 4
      app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
  5. 14
      app/src/main/java/gr/thmmy/mthmmy/utils/TakePhoto.java

1
app/build.gradle

@ -46,6 +46,7 @@ dependencies {
implementation 'com.google.firebase:firebase-core:16.0.3' implementation 'com.google.firebase:firebase-core:16.0.3'
implementation 'com.google.firebase:firebase-messaging:17.3.0' implementation 'com.google.firebase:firebase-messaging:17.3.0'
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.5' implementation 'com.crashlytics.sdk.android:crashlytics:2.9.5'
implementation 'com.snatik:storage:2.1.0'
implementation 'com.squareup.okhttp3:okhttp:3.10.0' implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.picasso:picasso:2.5.2' implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0' implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'

118
app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java

@ -5,16 +5,21 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment;
import android.provider.OpenableColumns;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton; import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.FileProvider;
import android.support.v7.content.res.AppCompatResources; import android.support.v7.content.res.AppCompatResources;
import android.support.v7.preference.PreferenceManager; import android.support.v7.preference.PreferenceManager;
import android.support.v7.widget.AppCompatButton; import android.support.v7.widget.AppCompatButton;
import android.support.v7.widget.AppCompatTextView; import android.support.v7.widget.AppCompatTextView;
import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
@ -23,6 +28,9 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.Toast; import android.widget.Toast;
import com.snatik.storage.Storage;
import net.gotev.uploadservice.MultipartUploadRequest; import net.gotev.uploadservice.MultipartUploadRequest;
import net.gotev.uploadservice.ServerResponse; import net.gotev.uploadservice.ServerResponse;
import net.gotev.uploadservice.UploadInfo; import net.gotev.uploadservice.UploadInfo;
@ -74,15 +82,25 @@ public class UploadActivity extends BaseActivity {
*/ */
private static final int UPLOAD_REQUEST_CODE = 42; //Arbitrary, application specific private static final int UPLOAD_REQUEST_CODE = 42; //Arbitrary, application specific
private static final int NO_UPLOAD_METHOD_SELECTED = 0;
private static final int SELECT_FILE_METHOD_SELECTED = 1;
private static final int TAKE_PHOTO_METHOD_SELECTED = 2;
private static final String TEMPORARY_FILES_DIRECTORY = "~tmp_mThmmy_uploads";
private static final int MAX_FILE_SIZE_SUPPORTED = 45000000;
private ArrayList<UploadCategory> uploadRootCategories = new ArrayList<>(); private ArrayList<UploadCategory> uploadRootCategories = new ArrayList<>();
private ParseUploadPageTask parseUploadPageTask; private ParseUploadPageTask parseUploadPageTask;
private ArrayList<String> bundleCategory; private ArrayList<String> bundleCategory;
private String categorySelected = "-1"; private String categorySelected = "-1";
private String uploaderProfileIndex = "1"; private String uploaderProfileIndex = "1";
private String uploadFilename;
private int uploadMethodSelected = NO_UPLOAD_METHOD_SELECTED;
private Uri fileUri; private Uri fileUri;
private File photoFileSelected = null;
private File photoFileCreated = null;
private String fileIcon; private String fileIcon;
private File photoFile = null; private String generatorUploadFilename;
//UI elements //UI elements
private MaterialProgressBar progressBar; private MaterialProgressBar progressBar;
@ -229,41 +247,73 @@ public class UploadActivity extends BaseActivity {
FloatingActionButton uploadFAB = findViewById(R.id.upload_fab); FloatingActionButton uploadFAB = findViewById(R.id.upload_fab);
uploadFAB.setOnClickListener(view -> { uploadFAB.setOnClickListener(view -> {
//Attempts upload
progressBar.setVisibility(View.VISIBLE); progressBar.setVisibility(View.VISIBLE);
String uploadTitleText = uploadTitle.getText().toString(); String uploadTitleText = uploadTitle.getText().toString();
String uploadDescriptionText = uploadDescription.getText().toString(); String uploadDescriptionText = uploadDescription.getText().toString();
//Checks if all required fields are filled
{
boolean shouldReturn = false;
if (uploadTitleText.equals("")) { if (uploadTitleText.equals("")) {
uploadTitle.setError("Required"); uploadTitle.setError("Required");
shouldReturn = true;
} }
if (fileUri == null) { if (fileUri == null) {
Toast.makeText(view.getContext(), "Please choose a file to upload or take a photo", Toast.LENGTH_LONG).show(); Toast.makeText(view.getContext(), "Please choose a file to upload or take a photo", Toast.LENGTH_LONG).show();
shouldReturn = true;
} }
if (categorySelected.equals("-1")) { if (categorySelected.equals("-1")) {
Toast.makeText(view.getContext(), "Please choose category first", Toast.LENGTH_SHORT).show(); Toast.makeText(view.getContext(), "Please choose category first", Toast.LENGTH_SHORT).show();
shouldReturn = true;
} }
if (UploadsHelper.sizeFromUri(this, fileUri) > MAX_FILE_SIZE_SUPPORTED) {
if (categorySelected.equals("-1") || uploadTitleText.equals("") || fileUri == null) { Toast.makeText(view.getContext(), "Your files are too powerful for thmmy. Reduce size or split!", Toast.LENGTH_LONG).show();
shouldReturn = true;
}
if (shouldReturn) {
progressBar.setVisibility(View.GONE); progressBar.setVisibility(View.GONE);
return; return;
} }
}
//Checks settings and adds "Uploaded from mTHMMY" string to description
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(view.getContext()); SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(view.getContext());
if (sharedPrefs.getBoolean(UPLOADING_APP_SIGNATURE_ENABLE_KEY, true)) { if (sharedPrefs.getBoolean(UPLOADING_APP_SIGNATURE_ENABLE_KEY, true)) {
uploadDescriptionText += uploadedFromThmmyPromptHtml; uploadDescriptionText += uploadedFromThmmyPromptHtml;
} }
String tempFilePath = null; //Checks if the generator was used
if (uploadFilename != null) { if (generatorUploadFilename != null) {
//File should be uploaded with a certain name. Temporarily copies the file and renames it //File should be uploaded with a certain name.
tempFilePath = UploadsHelper.createTempFile(this, fileUri, uploadFilename); switch (uploadMethodSelected) {
if (tempFilePath == null) { case SELECT_FILE_METHOD_SELECTED:
//Temporarily copies the file to a another location and renames it
fileUri = UploadsHelper.createTempFile(this, storage, fileUri,
generatorUploadFilename);
break;
case TAKE_PHOTO_METHOD_SELECTED:
//Renames the photo taken
String photoPath = photoFileSelected.getPath();
photoPath = photoPath.substring(0, photoPath.lastIndexOf(File.separator));
String destinationFilename = photoPath + File.separator + generatorUploadFilename + ".jpg";
if (!storage.rename(photoFileSelected.getAbsolutePath(), destinationFilename)) {
//Something went wrong, abort //Something went wrong, abort
Toast.makeText(this, "Could not create temporary file for renaming", Toast.LENGTH_SHORT).show(); Toast.makeText(this, "Could not create temporary file for renaming", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE); progressBar.setVisibility(View.GONE);
return; return;
} }
//Points photoFile and fileUri to the new copied and renamed file
photoFileSelected = storage.getFile(destinationFilename);
fileUri = FileProvider.getUriForFile(this, getPackageName() +
".provider", photoFileSelected);
break;
default:
break;
}
} }
try { try {
@ -272,10 +322,7 @@ public class UploadActivity extends BaseActivity {
.addParameter("tp-dluploadtitle", uploadTitleText) .addParameter("tp-dluploadtitle", uploadTitleText)
.addParameter("tp-dluploadcat", categorySelected) .addParameter("tp-dluploadcat", categorySelected)
.addParameter("tp-dluploadtext", uploadDescriptionText) .addParameter("tp-dluploadtext", uploadDescriptionText)
.addFileToUpload(tempFilePath == null .addFileToUpload(fileUri.toString(), "tp-dluploadfile")
? fileUri.toString()
: tempFilePath
, "tp-dluploadfile")
.addParameter("tp_dluploadicon", fileIcon) .addParameter("tp_dluploadicon", fileIcon)
.addParameter("tp-uploaduser", uploaderProfileIndex) .addParameter("tp-uploaduser", uploaderProfileIndex)
.setNotificationConfig(new UploadNotificationConfig()) .setNotificationConfig(new UploadNotificationConfig())
@ -299,9 +346,15 @@ public class UploadActivity extends BaseActivity {
UploadsHelper.deleteTempFiles(); UploadsHelper.deleteTempFiles();
BaseApplication.getInstance().logFirebaseAnalyticsEvent("file_upload", null); BaseApplication.getInstance().logFirebaseAnalyticsEvent("file_upload", null);
if (uploadMethodSelected == TAKE_PHOTO_METHOD_SELECTED) {
TakePhoto.galleryAddPic(context, photoFileSelected);
}
uploadTitle.setText(null); uploadTitle.setText(null);
uploadDescription.setText(null); uploadDescription.setText(null);
fileUri = null; fileUri = null;
photoFileCreated = null;
photoFileSelected = null;
filenameHolder.setText(null); filenameHolder.setText(null);
filenameHolder.setVisibility(View.GONE); filenameHolder.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE); progressBar.setVisibility(View.GONE);
@ -353,6 +406,14 @@ public class UploadActivity extends BaseActivity {
super.onDestroy(); super.onDestroy();
if (parseUploadPageTask != null && parseUploadPageTask.getStatus() != AsyncTask.Status.RUNNING) if (parseUploadPageTask != null && parseUploadPageTask.getStatus() != AsyncTask.Status.RUNNING)
parseUploadPageTask.cancel(true); parseUploadPageTask.cancel(true);
//Deletes any photo file previously created, as it is not going to be used
if (photoFileCreated != null) {
storage.deleteFile(photoFileCreated.getAbsolutePath());
}
if (photoFileSelected != null) {
storage.deleteFile(photoFileSelected.getAbsolutePath());
}
} }
@Override @Override
@ -362,6 +423,15 @@ public class UploadActivity extends BaseActivity {
return; return;
} }
//Deletes any photo file previously created, as it is not going to be used
if (photoFileCreated != null) {
storage.deleteFile(photoFileCreated.getAbsolutePath());
}
if (photoFileSelected != null) {
storage.deleteFile(photoFileSelected.getAbsolutePath());
}
uploadMethodSelected = SELECT_FILE_METHOD_SELECTED;
fileUri = data.getData(); fileUri = data.getData();
if (fileUri != null) { if (fileUri != null) {
String filename = UploadsHelper.filenameFromUri(this, fileUri); String filename = UploadsHelper.filenameFromUri(this, fileUri);
@ -390,12 +460,20 @@ public class UploadActivity extends BaseActivity {
} }
} else if (requestCode == AFR_REQUEST_CODE_CAMERA) { } else if (requestCode == AFR_REQUEST_CODE_CAMERA) {
if (resultCode == Activity.RESULT_CANCELED) { if (resultCode == Activity.RESULT_CANCELED) {
//Deletes image file
storage.deleteFile(photoFileCreated.getAbsolutePath());
return; return;
} }
uploadMethodSelected = TAKE_PHOTO_METHOD_SELECTED;
fileUri = TakePhoto.processResult(this, photoFile); if (photoFileSelected != null) {
storage.deleteFile(photoFileSelected.getAbsolutePath());
}
photoFileSelected = photoFileCreated;
fileUri = TakePhoto.processResult(this, photoFileSelected);
filenameHolder.setText(photoFile.getName()); filenameHolder.setText(photoFileSelected.getName());
filenameHolder.setVisibility(View.VISIBLE); filenameHolder.setVisibility(View.VISIBLE);
fileIcon = "jpg_image.gif"; fileIcon = "jpg_image.gif";
} else if (requestCode == AFR_REQUEST_CODE_FIELDS_BUILDER) { } else if (requestCode == AFR_REQUEST_CODE_FIELDS_BUILDER) {
@ -403,7 +481,7 @@ public class UploadActivity extends BaseActivity {
return; return;
} }
uploadFilename = data.getStringExtra(RESULT_FILENAME); generatorUploadFilename = data.getStringExtra(RESULT_FILENAME);
uploadTitle.setText(data.getStringExtra(RESULT_TITLE)); uploadTitle.setText(data.getStringExtra(RESULT_TITLE));
uploadDescription.setText(data.getStringExtra(RESULT_DESCRIPTION)); uploadDescription.setText(data.getStringExtra(RESULT_DESCRIPTION));
} else { } else {
@ -425,11 +503,13 @@ public class UploadActivity extends BaseActivity {
// Should only be called after making sure permissions are granted // Should only be called after making sure permissions are granted
private void takePhoto() { private void takePhoto() {
// Create the File where the photo should go // Create the File where the photo should go
photoFile = TakePhoto.createImageFile(this); photoFileCreated = TakePhoto.createImageFile(this);
// Continue only if the File was successfully created // Continue only if the File was successfully created
if (photoFile != null) if (photoFileCreated != null) {
startActivityForResult(TakePhoto.getIntent(this, photoFile), AFR_REQUEST_CODE_CAMERA); startActivityForResult(TakePhoto.getIntent(this, photoFileCreated),
AFR_REQUEST_CODE_CAMERA);
}
} }
private class CustomOnItemSelectedListener implements AdapterView.OnItemSelectedListener { private class CustomOnItemSelectedListener implements AdapterView.OnItemSelectedListener {

70
app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java

@ -1,13 +1,7 @@
package gr.thmmy.mthmmy.activities.upload; package gr.thmmy.mthmmy.activities.upload;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri; import android.net.Uri;
import android.os.Environment; import android.os.Environment;
import android.provider.OpenableColumns; import android.provider.OpenableColumns;
@ -16,46 +10,21 @@ import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider; import android.support.v4.content.FileProvider;
import android.widget.Toast; import android.widget.Toast;
import com.snatik.storage.Storage;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import timber.log.Timber; import timber.log.Timber;
import static android.support.v4.content.FileProvider.getUriForFile;
class UploadsHelper { class UploadsHelper {
@NonNull
static String filenameFromUri(Context context, Uri uri) {
String filename = null;
if (uri.getScheme().equals("content")) {
try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
}
}
if (filename == null) {
filename = uri.getPath();
int cut = filename.lastIndexOf('/');
if (cut != -1) {
filename = filename.substring(cut + 1);
}
}
return filename;
}
@SuppressWarnings("ResultOfMethodCallIgnored") @SuppressWarnings("ResultOfMethodCallIgnored")
@Nullable @Nullable
static String createTempFile(Context context, Uri fileUri, String newFilename) { static Uri createTempFile(Context context, Storage storage, Uri fileUri, String newFilename) {
String oldFilename = filenameFromUri(context, fileUri); String oldFilename = filenameFromUri(context, fileUri);
String fileExtension = oldFilename.substring(oldFilename.indexOf(".")); String fileExtension = oldFilename.substring(oldFilename.indexOf("."));
String destinationFilename = Environment.getExternalStorageDirectory().getPath() + String destinationFilename = Environment.getExternalStorageDirectory().getPath() +
@ -101,7 +70,38 @@ class UploadsHelper {
} }
} }
return destinationFilename; return FileProvider.getUriForFile(context, context.getPackageName() +
".provider", storage.getFile(destinationFilename));
}
@NonNull
static String filenameFromUri(Context context, Uri uri) {
String filename = null;
if (uri.getScheme().equals("content")) {
try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
}
}
if (filename == null) {
filename = uri.getPath();
int cut = filename.lastIndexOf('/');
if (cut != -1) {
filename = filename.substring(cut + 1);
}
}
return filename;
}
static long sizeFromUri(Context context, Uri uri){
try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
return cursor.getLong(cursor.getColumnIndex(OpenableColumns.SIZE));
}
}
return -1;
} }
@SuppressWarnings("ResultOfMethodCallIgnored") @SuppressWarnings("ResultOfMethodCallIgnored")

4
app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java

@ -37,6 +37,7 @@ import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
import com.mikepenz.materialdrawer.model.ProfileDrawerItem; import com.mikepenz.materialdrawer.model.ProfileDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem; import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IProfile; import com.mikepenz.materialdrawer.model.interfaces.IProfile;
import com.snatik.storage.Storage;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
@ -90,6 +91,7 @@ public abstract class BaseActivity extends AppCompatActivity {
//Common UI elements //Common UI elements
protected Toolbar toolbar; protected Toolbar toolbar;
protected Drawer drawer; protected Drawer drawer;
protected Storage storage;
private MainActivity mainActivity; private MainActivity mainActivity;
@ -112,6 +114,8 @@ public abstract class BaseActivity extends AppCompatActivity {
baseViewModel.getCurrentPageBookmark().observe(this, thisPageBookmark -> { baseViewModel.getCurrentPageBookmark().observe(this, thisPageBookmark -> {
setTopicBookmark(thisPageBookmarkMenuButton); setTopicBookmark(thisPageBookmarkMenuButton);
}); });
storage = new Storage(getApplicationContext());
} }
@Override @Override

14
app/src/main/java/gr/thmmy/mthmmy/utils/TakePhoto.java

@ -11,12 +11,14 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.media.ExifInterface; import android.media.ExifInterface;
import android.media.MediaScannerConnection;
import android.net.Uri; import android.net.Uri;
import android.os.Environment; import android.os.Environment;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider; import android.support.v4.content.FileProvider;
import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
import java.io.File; import java.io.File;
@ -31,6 +33,7 @@ import timber.log.Timber;
public class TakePhoto { public class TakePhoto {
private static final int DEFAULT_MIN_WIDTH_QUALITY = 400; private static final int DEFAULT_MIN_WIDTH_QUALITY = 400;
private static final String IMAGE_CONTENT_DESCRIPTION = "mThmmy uploads image";
@Nullable @Nullable
public static Intent getIntent(Context context, @NonNull File photoFile) { public static Intent getIntent(Context context, @NonNull File photoFile) {
@ -92,17 +95,14 @@ public class TakePhoto {
} }
} }
File photoFile = new File(imageFolder, imageFileName); return new File(imageFolder, imageFileName);
galleryAddPic(context, photoFile);
return photoFile;
} }
private static void galleryAddPic(Context context, File photoFile) { public static void galleryAddPic(Context context, File photoFile) {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, photoFile.getName()); values.put(MediaStore.Images.Media.TITLE, photoFile.getName());
values.put(MediaStore.Images.Media.DESCRIPTION, "mThmmy uploads image"); values.put(MediaStore.Images.Media.DESCRIPTION, IMAGE_CONTENT_DESCRIPTION);
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()); //TODO fix bug values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaStore.Images.ImageColumns.BUCKET_ID, photoFile.toString().toLowerCase(Locale.US).hashCode()); values.put(MediaStore.Images.ImageColumns.BUCKET_ID, photoFile.toString().toLowerCase(Locale.US).hashCode());
values.put(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, photoFile.getName().toLowerCase(Locale.US)); values.put(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, photoFile.getName().toLowerCase(Locale.US));
values.put("_data", photoFile.getAbsolutePath()); values.put("_data", photoFile.getAbsolutePath());

Loading…
Cancel
Save