Browse Source

Multiple files upload init

uploads
Apostolos Fanakis 6 years ago
parent
commit
8e7499142e
  1. 214
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadActivity.java
  2. 58
      app/src/main/java/gr/thmmy/mthmmy/activities/upload/UploadsHelper.java
  3. 44
      app/src/main/java/gr/thmmy/mthmmy/model/UploadFile.java
  4. 4
      app/src/main/res/drawable/ic_attach_file_white_24dp.xml
  5. 9
      app/src/main/res/layout/activity_upload.xml
  6. 23
      app/src/main/res/layout/activity_upload_file_list_row.xml

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

@ -50,6 +50,7 @@ import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.base.BaseActivity;
import gr.thmmy.mthmmy.base.BaseApplication;
import gr.thmmy.mthmmy.model.UploadCategory;
import gr.thmmy.mthmmy.model.UploadFile;
import gr.thmmy.mthmmy.utils.AppCompatSpinnerWithoutDefault;
import gr.thmmy.mthmmy.utils.FileUtils;
import gr.thmmy.mthmmy.utils.TakePhoto;
@ -84,10 +85,6 @@ 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 int MAX_FILE_SIZE_SUPPORTED = 45000000;
private ArrayList<UploadCategory> uploadRootCategories = new ArrayList<>();
@ -96,9 +93,7 @@ public class UploadActivity extends BaseActivity {
private String categorySelected = "-1";
private String uploaderProfileIndex = "1";
private int uploadMethodSelected = NO_UPLOAD_METHOD_SELECTED;
private Uri fileUri;
private File photoFileSelected = null;
private ArrayList<UploadFile> filesList = new ArrayList<>();
private File photoFileCreated = null;
private String fileIcon;
@ -110,6 +105,7 @@ public class UploadActivity extends BaseActivity {
private EditText uploadFilename;
private EditText uploadDescription;
private AppCompatButton titleDescriptionBuilderButton;
private LinearLayout filesListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -247,9 +243,16 @@ public class UploadActivity extends BaseActivity {
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
oldFilename = s.toString();
if (fileUri != null) {
String uriExtension = FileUtils.getFileExtension(FileUtils.
filenameFromUri(getApplicationContext(), fileUri));
String uriExtension;
if (filesList.isEmpty()) {
fileExtension = null;
return;
} else if (filesList.size() == 1) {
uriExtension = FileUtils.getFileExtension(FileUtils.
filenameFromUri(getApplicationContext(), filesList.get(0).getFileUri()));
} else {
uriExtension = ".zip";
}
if (fileExtension == null || !fileExtension.equals(uriExtension)) {
//New file selected
@ -257,11 +260,7 @@ public class UploadActivity extends BaseActivity {
oldFilename = FileUtils.getFilenameWithoutExtension(oldFilename) +
uriExtension;
}
fileExtension = uriExtension;
} else {
fileExtension = null;
}
}
@Override
@ -293,6 +292,8 @@ public class UploadActivity extends BaseActivity {
}
});
filesListView = findViewById(R.id.upload_files_list);
AppCompatButton selectFileButton = findViewById(R.id.upload_select_file_button);
Drawable selectStartDrawable = AppCompatResources.getDrawable(this, R.drawable.ic_insert_drive_file_white_24dp);
selectFileButton.setCompoundDrawablesRelativeWithIntrinsicBounds(selectStartDrawable, null, null, null);
@ -335,7 +336,7 @@ public class UploadActivity extends BaseActivity {
uploadTitle.setError("Required");
shouldReturn = true;
}
if (fileUri == null) {
if (filesList.isEmpty()) {
Toast.makeText(view.getContext(), "Please choose a file to upload or take a photo", Toast.LENGTH_LONG).show();
shouldReturn = true;
}
@ -343,10 +344,17 @@ public class UploadActivity extends BaseActivity {
Toast.makeText(view.getContext(), "Please choose category first", Toast.LENGTH_SHORT).show();
shouldReturn = true;
}
if (fileUri != null && FileUtils.sizeFromUri(this, fileUri) > MAX_FILE_SIZE_SUPPORTED) {
if (!filesList.isEmpty()) {
long totalFilesSize = 0;
for (UploadFile file : filesList) {
totalFilesSize += FileUtils.sizeFromUri(this, file.getFileUri());
}
if (totalFilesSize > 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 (!editTextFilename.matches("(.+\\.)+.+")) {
uploadFilename.setError("Invalid filename");
shouldReturn = true;
@ -363,27 +371,27 @@ public class UploadActivity extends BaseActivity {
uploadDescriptionText += uploadedFromThmmyPromptHtml;
}
//Checks if a file renaming is necessary
Uri tempFileUri = null;
{
String selectedFileFilename = FileUtils.filenameFromUri(this, fileUri);
if (filesList.size() == 1) {
//Checks if the file needs renaming
UploadFile uploadFile = filesList.get(0);
String selectedFileFilename = FileUtils.filenameFromUri(this, uploadFile.getFileUri());
if (!editTextFilename.equals(selectedFileFilename)) {
//File should be uploaded with a different name
switch (uploadMethodSelected) {
case SELECT_FILE_METHOD_SELECTED:
if (!uploadFile.isCameraPhoto()) {
//Temporarily copies the file to a another location and renames it
tempFileUri = UploadsHelper.createTempFile(this, storage, fileUri,
tempFileUri = UploadsHelper.createTempFile(this, storage,
uploadFile.getFileUri(),
FileUtils.getFilenameWithoutExtension(editTextFilename));
break;
case TAKE_PHOTO_METHOD_SELECTED:
} else {
//Renames the photo taken
String photoPath = photoFileSelected.getPath();
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(photoFileSelected.getAbsolutePath(), destinationFilename)) {
if (!storage.rename(uploadFile.getPhotoFile().getAbsolutePath(), destinationFilename)) {
//Something went wrong, abort
Toast.makeText(this, "Could not create temporary file for renaming", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
@ -391,14 +399,23 @@ public class UploadActivity extends BaseActivity {
}
//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;
uploadFile.setPhotoFile(storage.getFile(destinationFilename));
uploadFile.setFileUri(FileProvider.getUriForFile(this, getPackageName() +
".provider", uploadFile.getPhotoFile()));
}
}
} else {
Uri[] filesListArray = new Uri[filesList.size()];
for (int i = 0; i < filesList.size(); ++i) {
filesListArray[i] = filesList.get(i).getFileUri();
}
File zipFile = UploadsHelper.createZipFile(this);
assert zipFile != null;
tempFileUri = FileProvider.getUriForFile(this, getPackageName() +
".provider", zipFile);
UploadsHelper.zip(this, filesListArray, tempFileUri);
}
try {
@ -408,7 +425,7 @@ public class UploadActivity extends BaseActivity {
.addParameter("tp-dluploadcat", categorySelected)
.addParameter("tp-dluploadtext", uploadDescriptionText)
.addFileToUpload(tempFileUri == null
? fileUri.toString()
? filesList.get(0).getFileUri().toString()
: tempFileUri.toString()
, "tp-dluploadfile")
.addParameter("tp_dluploadicon", fileIcon)
@ -434,15 +451,18 @@ public class UploadActivity extends BaseActivity {
UploadsHelper.deleteTempFiles();
BaseApplication.getInstance().logFirebaseAnalyticsEvent("file_upload", null);
if (uploadMethodSelected == TAKE_PHOTO_METHOD_SELECTED) {
TakePhoto.galleryAddPic(context, photoFileSelected);
for (UploadFile file : filesList) {
if (file.isCameraPhoto()) {
TakePhoto.galleryAddPic(context, file.getPhotoFile());
}
}
uploadTitle.setText(null);
uploadFilename.setText(null);
uploadDescription.setText(null);
fileUri = null;
filesList.clear();
filesListView.removeAllViews();
photoFileCreated = null;
photoFileSelected = null;
progressBar.setVisibility(View.GONE);
}
@ -497,9 +517,6 @@ public class UploadActivity extends BaseActivity {
if (photoFileCreated != null) {
storage.deleteFile(photoFileCreated.getAbsolutePath());
}
if (photoFileSelected != null) {
storage.deleteFile(photoFileSelected.getAbsolutePath());
}
}
@Override
@ -509,41 +526,13 @@ public class UploadActivity extends BaseActivity {
return;
}
//Keeps the filename between different file selections if it has been modified
boolean hasCustomFilename = false;
{
String editTextFilename = FileUtils.
getFilenameWithoutExtension(uploadFilename.getText().toString());
String previousFilename = "";
if (fileUri != null) {
previousFilename = FileUtils.
getFilenameWithoutExtension(FileUtils.filenameFromUri(this, fileUri));
}
if (editTextFilename != null && !editTextFilename.isEmpty() &&
!editTextFilename.equals(previousFilename)) {
hasCustomFilename = 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());
}
uploadMethodSelected = SELECT_FILE_METHOD_SELECTED;
Uri newFileUri = data.getData();
if (newFileUri != null) {
String filename = FileUtils.filenameFromUri(this, newFileUri);
fileUri = data.getData();
if (fileUri != null) {
String filename = FileUtils.filenameFromUri(this, fileUri);
if (!hasCustomFilename) {
if (filesList.isEmpty()) {
if (uploadFilename.getText().toString().isEmpty()) {
uploadFilename.setText(filename);
} else {
//Causes the EditText watcher to detect the fileUri change in case the extension changed
String badHack = "stringThatIntentionallyInvalidatesFilename";
uploadFilename.setText(badHack);
}
filename = filename.toLowerCase();
@ -565,6 +554,17 @@ public class UploadActivity extends BaseActivity {
} else {
fileIcon = "blank.gif";
}
} else {
fileIcon = "archive.gif";
String currentFilename = uploadFilename.getText().toString();
String newFilename = FileUtils.getFilenameWithoutExtension(currentFilename) +
".zip";
uploadFilename.setText(newFilename);
}
addFileViewToList(filename);
filesList.add(new UploadFile(false, newFileUri, null));
}
} else if (requestCode == AFR_REQUEST_CODE_CAMERA) {
if (resultCode == Activity.RESULT_CANCELED) {
@ -572,41 +572,27 @@ public class UploadActivity extends BaseActivity {
storage.deleteFile(photoFileCreated.getAbsolutePath());
return;
}
uploadMethodSelected = TAKE_PHOTO_METHOD_SELECTED;
//Keeps the filename between different file selections if it has been modified
boolean hasCustomFilename = false;
{
String editTextFilename = FileUtils.
getFilenameWithoutExtension(uploadFilename.getText().toString());
String previousFilename = "";
if (fileUri != null) {
previousFilename = FileUtils.
getFilenameWithoutExtension(FileUtils.filenameFromUri(this, fileUri));
}
if (editTextFilename != null && !editTextFilename.isEmpty() &&
!editTextFilename.equals(previousFilename)) {
hasCustomFilename = true;
if (filesList.isEmpty()) {
if (uploadFilename.getText().toString().isEmpty()) {
uploadFilename.setText(photoFileCreated.getName());
}
}
if (photoFileSelected != null) {
storage.deleteFile(photoFileSelected.getAbsolutePath());
}
photoFileSelected = photoFileCreated;
fileUri = TakePhoto.processResult(this, photoFileSelected);
if (!hasCustomFilename) {
uploadFilename.setText(photoFileSelected.getName());
fileIcon = "jpg_image.gif";
} else {
//Causes the EditText watcher to detect the fileUri change in case the extension changed
String badHack = "stringThatIntentionallyInvalidatesFilename";
uploadFilename.setText(badHack);
fileIcon = "archive.gif";
String currentFilename = uploadFilename.getText().toString();
String newFilename = FileUtils.getFilenameWithoutExtension(currentFilename) +
".zip";
uploadFilename.setText(newFilename);
}
fileIcon = "jpg_image.gif";
UploadFile newFile = new UploadFile(true, TakePhoto.processResult(this,
photoFileCreated), photoFileCreated);
addFileViewToList(FileUtils.getFilenameWithoutExtension(FileUtils.
filenameFromUri(this, newFile.getFileUri())));
filesList.add(newFile);
} else if (requestCode == AFR_REQUEST_CODE_FIELDS_BUILDER) {
if (resultCode == Activity.RESULT_CANCELED) {
return;
@ -651,6 +637,30 @@ public class UploadActivity extends BaseActivity {
}
}
private void addFileViewToList(String filename) {
LayoutInflater layoutInflater = getLayoutInflater();
LinearLayout newFileRow = (LinearLayout) layoutInflater.
inflate(R.layout.activity_upload_file_list_row, null);
TextView itemText = newFileRow.findViewById(R.id.upload_file_item_text);
Drawable filenameDrawable = AppCompatResources.getDrawable(this, R.drawable.ic_attach_file_white_24dp);
itemText.setCompoundDrawablesRelativeWithIntrinsicBounds(filenameDrawable, null, null, null);
itemText.setText(filename);
newFileRow.findViewById(R.id.upload_file_item_remove).
setOnClickListener(view -> {
int fileIndex = filesListView.indexOfChild(newFileRow);
filesListView.removeViewAt(fileIndex);
filesList.remove(fileIndex);
if (filesList.isEmpty()) {
filesListView.setVisibility(View.GONE);
}
});
filesListView.addView(newFileRow);
filesListView.setVisibility(View.VISIBLE);
}
private class CustomOnItemSelectedListener implements AdapterView.OnItemSelectedListener {
private ArrayList<UploadCategory> parentCategories, childCategories;

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

@ -15,11 +15,19 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import gr.thmmy.mthmmy.utils.FileUtils;
import timber.log.Timber;
class UploadsHelper {
private final static int BUFFER = 4096;
@SuppressWarnings("ResultOfMethodCallIgnored")
@Nullable
static Uri createTempFile(Context context, Storage storage, Uri fileUri, String newFilename) {
@ -70,6 +78,56 @@ class UploadsHelper {
return FileProvider.getUriForFile(context, context.getPackageName() +
".provider", storage.getFile(destinationFilename));
}
@Nullable
public static File createZipFile(Context context) {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.FRANCE).format(new Date());
String zipFileName = "mThmmy_" + timeStamp + ".zip";
File zipFolder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) +
File.separator + "mThmmy");
if (!zipFolder.exists()) {
if (!zipFolder.mkdirs()) {
Timber.w("Zip folder build returned false in %s", UploadsHelper.class.getSimpleName());
Toast.makeText(context, "Couldn't create zip directory", Toast.LENGTH_SHORT).show();
return null;
}
}
return new File(zipFolder, zipFileName);
}
public static void zip(Context context, Uri[] files, Uri zipFile) {
try {
BufferedInputStream origin;
OutputStream dest = context.getContentResolver().openOutputStream(zipFile);
assert dest != null;
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
byte data[] = new byte[BUFFER];
for (Uri file : files) {
InputStream inputStream = context.getContentResolver().openInputStream(file);
assert inputStream != null;
origin = new BufferedInputStream(inputStream, BUFFER);
ZipEntry entry = new ZipEntry(FileUtils.filenameFromUri(context, file));
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
}
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("ResultOfMethodCallIgnored")

44
app/src/main/java/gr/thmmy/mthmmy/model/UploadFile.java

@ -0,0 +1,44 @@
package gr.thmmy.mthmmy.model;
import android.net.Uri;
import android.support.annotation.Nullable;
import java.io.File;
public class UploadFile {
private final boolean isCameraPhoto;
private Uri fileUri;
private File photoFile;
private UploadFile() {
isCameraPhoto = false;
fileUri = null;
photoFile = null;
}
public UploadFile(boolean isCameraPhoto, Uri fileUri, @Nullable File photoFile) {
this.isCameraPhoto = isCameraPhoto;
this.fileUri = fileUri;
this.photoFile = photoFile;
}
public boolean isCameraPhoto() {
return isCameraPhoto;
}
public Uri getFileUri() {
return fileUri;
}
public File getPhotoFile() {
return photoFile;
}
public void setFileUri(Uri fileUri) {
this.fileUri = fileUri;
}
public void setPhotoFile(File photoFile) {
this.photoFile = photoFile;
}
}

4
app/src/main/res/drawable/ic_attach_file_white_24dp.xml

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="24dp">
<path android:fillColor="#FFFFFF" android:pathData="M16.5,6v11.5c0,2.21 -1.79,4 -4,4s-4,-1.79 -4,-4V5c0,-1.38 1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5v10.5c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V6H10v9.5c0,1.38 1.12,2.5 2.5,2.5s2.5,-1.12 2.5,-2.5V5c0,-2.21 -1.79,-4 -4,-4S7,2.79 7,5v12.5c0,3.04 2.46,5.5 5.5,5.5s5.5,-2.46 5.5,-5.5V6h-1.5z"/>
</vector>

9
app/src/main/res/layout/activity_upload.xml

@ -128,6 +128,15 @@
android:textAlignment="center"
android:textColor="@color/accent" />
<LinearLayout
android:id="@+id/upload_files_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="6dp"
android:layout_marginTop="6dp"
android:orientation="vertical"
android:visibility="gone" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

23
app/src/main/res/layout/activity_upload_file_list_row.xml

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<android.support.v7.widget.AppCompatTextView
android:id="@+id/upload_file_item_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawablePadding="5dp"
android:ellipsize="marquee"
android:singleLine="true"
android:textColor="@color/primary_text" />
<android.support.v7.widget.AppCompatImageButton
android:id="@+id/upload_file_item_remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_delete_accent_24dp" />
</LinearLayout>
Loading…
Cancel
Save