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. 158
      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-messaging:17.3.0'
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.picasso:picasso:2.5.2'
implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'

158
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.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.OpenableColumns;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.FileProvider;
import android.support.v7.content.res.AppCompatResources;
import android.support.v7.preference.PreferenceManager;
import android.support.v7.widget.AppCompatButton;
import android.support.v7.widget.AppCompatTextView;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
@ -23,6 +28,9 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.snatik.storage.Storage;
import net.gotev.uploadservice.MultipartUploadRequest;
import net.gotev.uploadservice.ServerResponse;
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 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 ParseUploadPageTask parseUploadPageTask;
private ArrayList<String> bundleCategory;
private String categorySelected = "-1";
private String uploaderProfileIndex = "1";
private String uploadFilename;
private int uploadMethodSelected = NO_UPLOAD_METHOD_SELECTED;
private Uri fileUri;
private File photoFileSelected = null;
private File photoFileCreated = null;
private String fileIcon;
private File photoFile = null;
private String generatorUploadFilename;
//UI elements
private MaterialProgressBar progressBar;
@ -221,48 +239,80 @@ public class UploadActivity extends BaseActivity {
Drawable takePhotoDrawable = AppCompatResources.getDrawable(this, R.drawable.ic_photo_camera_white_24dp);
takePhotoButton.setCompoundDrawablesRelativeWithIntrinsicBounds(takePhotoDrawable, null, null, null);
takePhotoButton.setOnClickListener(v -> {
if(checkPerms())
takePhoto();
else
requestPerms(UPLOAD_REQUEST_CODE);
if (checkPerms())
takePhoto();
else
requestPerms(UPLOAD_REQUEST_CODE);
});
FloatingActionButton uploadFAB = findViewById(R.id.upload_fab);
uploadFAB.setOnClickListener(view -> {
//Attempts upload
progressBar.setVisibility(View.VISIBLE);
String uploadTitleText = uploadTitle.getText().toString();
String uploadDescriptionText = uploadDescription.getText().toString();
if (uploadTitleText.equals("")) {
uploadTitle.setError("Required");
}
if (fileUri == null) {
Toast.makeText(view.getContext(), "Please choose a file to upload or take a photo", Toast.LENGTH_LONG).show();
}
if (categorySelected.equals("-1")) {
Toast.makeText(view.getContext(), "Please choose category first", Toast.LENGTH_SHORT).show();
}
if (categorySelected.equals("-1") || uploadTitleText.equals("") || fileUri == null) {
progressBar.setVisibility(View.GONE);
return;
//Checks if all required fields are filled
{
boolean shouldReturn = false;
if (uploadTitleText.equals("")) {
uploadTitle.setError("Required");
shouldReturn = true;
}
if (fileUri == null) {
Toast.makeText(view.getContext(), "Please choose a file to upload or take a photo", Toast.LENGTH_LONG).show();
shouldReturn = true;
}
if (categorySelected.equals("-1")) {
Toast.makeText(view.getContext(), "Please choose category first", Toast.LENGTH_SHORT).show();
shouldReturn = true;
}
if (UploadsHelper.sizeFromUri(this, fileUri) > MAX_FILE_SIZE_SUPPORTED) {
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);
return;
}
}
//Checks settings and adds "Uploaded from mTHMMY" string to description
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(view.getContext());
if (sharedPrefs.getBoolean(UPLOADING_APP_SIGNATURE_ENABLE_KEY, true)) {
uploadDescriptionText += uploadedFromThmmyPromptHtml;
}
String tempFilePath = null;
if (uploadFilename != null) {
//File should be uploaded with a certain name. Temporarily copies the file and renames it
tempFilePath = UploadsHelper.createTempFile(this, fileUri, uploadFilename);
if (tempFilePath == null) {
//Something went wrong, abort
Toast.makeText(this, "Could not create temporary file for renaming", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
return;
//Checks if the generator was used
if (generatorUploadFilename != null) {
//File should be uploaded with a certain name.
switch (uploadMethodSelected) {
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
Toast.makeText(this, "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
photoFileSelected = storage.getFile(destinationFilename);
fileUri = FileProvider.getUriForFile(this, getPackageName() +
".provider", photoFileSelected);
break;
default:
break;
}
}
@ -272,10 +322,7 @@ public class UploadActivity extends BaseActivity {
.addParameter("tp-dluploadtitle", uploadTitleText)
.addParameter("tp-dluploadcat", categorySelected)
.addParameter("tp-dluploadtext", uploadDescriptionText)
.addFileToUpload(tempFilePath == null
? fileUri.toString()
: tempFilePath
, "tp-dluploadfile")
.addFileToUpload(fileUri.toString(), "tp-dluploadfile")
.addParameter("tp_dluploadicon", fileIcon)
.addParameter("tp-uploaduser", uploaderProfileIndex)
.setNotificationConfig(new UploadNotificationConfig())
@ -299,9 +346,15 @@ public class UploadActivity extends BaseActivity {
UploadsHelper.deleteTempFiles();
BaseApplication.getInstance().logFirebaseAnalyticsEvent("file_upload", null);
if (uploadMethodSelected == TAKE_PHOTO_METHOD_SELECTED) {
TakePhoto.galleryAddPic(context, photoFileSelected);
}
uploadTitle.setText(null);
uploadDescription.setText(null);
fileUri = null;
photoFileCreated = null;
photoFileSelected = null;
filenameHolder.setText(null);
filenameHolder.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
@ -353,6 +406,14 @@ public class UploadActivity extends BaseActivity {
super.onDestroy();
if (parseUploadPageTask != null && parseUploadPageTask.getStatus() != AsyncTask.Status.RUNNING)
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
@ -362,6 +423,15 @@ public class UploadActivity extends BaseActivity {
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();
if (fileUri != null) {
String filename = UploadsHelper.filenameFromUri(this, fileUri);
@ -390,12 +460,20 @@ public class UploadActivity extends BaseActivity {
}
} else if (requestCode == AFR_REQUEST_CODE_CAMERA) {
if (resultCode == Activity.RESULT_CANCELED) {
//Deletes image file
storage.deleteFile(photoFileCreated.getAbsolutePath());
return;
}
uploadMethodSelected = TAKE_PHOTO_METHOD_SELECTED;
if (photoFileSelected != null) {
storage.deleteFile(photoFileSelected.getAbsolutePath());
}
photoFileSelected = photoFileCreated;
fileUri = TakePhoto.processResult(this, photoFile);
fileUri = TakePhoto.processResult(this, photoFileSelected);
filenameHolder.setText(photoFile.getName());
filenameHolder.setText(photoFileSelected.getName());
filenameHolder.setVisibility(View.VISIBLE);
fileIcon = "jpg_image.gif";
} else if (requestCode == AFR_REQUEST_CODE_FIELDS_BUILDER) {
@ -403,7 +481,7 @@ public class UploadActivity extends BaseActivity {
return;
}
uploadFilename = data.getStringExtra(RESULT_FILENAME);
generatorUploadFilename = data.getStringExtra(RESULT_FILENAME);
uploadTitle.setText(data.getStringExtra(RESULT_TITLE));
uploadDescription.setText(data.getStringExtra(RESULT_DESCRIPTION));
} else {
@ -423,13 +501,15 @@ public class UploadActivity extends BaseActivity {
}
// Should only be called after making sure permissions are granted
private void takePhoto(){
private void takePhoto() {
// Create the File where the photo should go
photoFile = TakePhoto.createImageFile(this);
photoFileCreated = TakePhoto.createImageFile(this);
// Continue only if the File was successfully created
if (photoFile != null)
startActivityForResult(TakePhoto.getIntent(this, photoFile), AFR_REQUEST_CODE_CAMERA);
if (photoFileCreated != null) {
startActivityForResult(TakePhoto.getIntent(this, photoFileCreated),
AFR_REQUEST_CODE_CAMERA);
}
}
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;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
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.os.Environment;
import android.provider.OpenableColumns;
@ -16,46 +10,21 @@ import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider;
import android.widget.Toast;
import com.snatik.storage.Storage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import timber.log.Timber;
import static android.support.v4.content.FileProvider.getUriForFile;
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")
@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 fileExtension = oldFilename.substring(oldFilename.indexOf("."));
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")

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.interfaces.IDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
import com.snatik.storage.Storage;
import java.io.File;
import java.util.ArrayList;
@ -90,6 +91,7 @@ public abstract class BaseActivity extends AppCompatActivity {
//Common UI elements
protected Toolbar toolbar;
protected Drawer drawer;
protected Storage storage;
private MainActivity mainActivity;
@ -112,6 +114,8 @@ public abstract class BaseActivity extends AppCompatActivity {
baseViewModel.getCurrentPageBookmark().observe(this, thisPageBookmark -> {
setTopicBookmark(thisPageBookmarkMenuButton);
});
storage = new Storage(getApplicationContext());
}
@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.Matrix;
import android.media.ExifInterface;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
@ -31,6 +33,7 @@ import timber.log.Timber;
public class TakePhoto {
private static final int DEFAULT_MIN_WIDTH_QUALITY = 400;
private static final String IMAGE_CONTENT_DESCRIPTION = "mThmmy uploads image";
@Nullable
public static Intent getIntent(Context context, @NonNull File photoFile) {
@ -92,17 +95,14 @@ public class TakePhoto {
}
}
File photoFile = new File(imageFolder, imageFileName);
galleryAddPic(context, photoFile);
return photoFile;
return new File(imageFolder, imageFileName);
}
private static void galleryAddPic(Context context, File photoFile) {
public static void galleryAddPic(Context context, File photoFile) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, photoFile.getName());
values.put(MediaStore.Images.Media.DESCRIPTION, "mThmmy uploads image");
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis()); //TODO fix bug
values.put(MediaStore.Images.Media.DESCRIPTION, IMAGE_CONTENT_DESCRIPTION);
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_DISPLAY_NAME, photoFile.getName().toLowerCase(Locale.US));
values.put("_data", photoFile.getAbsolutePath());

Loading…
Cancel
Save