mirror of https://github.com/ThmmyNoLife/mTHMMY
oogee
5 years ago
94 changed files with 2801 additions and 1141 deletions
File diff suppressed because it is too large
@ -0,0 +1,79 @@ |
|||||
|
package gr.thmmy.mthmmy.activities.upload; |
||||
|
|
||||
|
import android.os.Bundle; |
||||
|
|
||||
|
import java.util.HashMap; |
||||
|
import java.util.Map; |
||||
|
import java.util.regex.Matcher; |
||||
|
import java.util.regex.Pattern; |
||||
|
|
||||
|
import gr.thmmy.mthmmy.base.BaseApplication; |
||||
|
import timber.log.Timber; |
||||
|
|
||||
|
class UploadsCourse { |
||||
|
private String name; |
||||
|
private String minifiedName; |
||||
|
private String greeklishName; |
||||
|
|
||||
|
private UploadsCourse(String fullName, String minifiedName, String greeklishName) { |
||||
|
this.name = fullName; |
||||
|
this.minifiedName = minifiedName; |
||||
|
this.greeklishName = greeklishName; |
||||
|
} |
||||
|
|
||||
|
String getName() { |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
String getMinifiedName() { |
||||
|
return minifiedName; |
||||
|
} |
||||
|
|
||||
|
String getGreeklishName() { |
||||
|
return greeklishName; |
||||
|
} |
||||
|
|
||||
|
static Map<String, UploadsCourse> generateUploadsCourses(String[] uploadsCoursesRes){ |
||||
|
Map<String, UploadsCourse> uploadsCourses = new HashMap<>(); |
||||
|
for(String uploadsCourseStr:uploadsCoursesRes) { |
||||
|
String[] split = uploadsCourseStr.split(":"); |
||||
|
UploadsCourse uploadsCourse = new UploadsCourse(split[0], split[1], split[2]); |
||||
|
uploadsCourses.put(uploadsCourse.getName(),uploadsCourse); |
||||
|
} |
||||
|
return uploadsCourses; |
||||
|
} |
||||
|
|
||||
|
static UploadsCourse findCourse(String retrievedCourse, |
||||
|
Map<String, UploadsCourse> uploadsCourses){ |
||||
|
retrievedCourse = normalizeGreekNumbers(retrievedCourse); |
||||
|
UploadsCourse uploadsCourse = uploadsCourses.get(retrievedCourse); |
||||
|
if(uploadsCourse != null) return uploadsCourse; |
||||
|
|
||||
|
String foundKey = null; |
||||
|
for (Map.Entry<String, UploadsCourse> entry : uploadsCourses.entrySet()) { |
||||
|
String key = entry.getKey(); |
||||
|
if ((key.contains(retrievedCourse) || retrievedCourse.contains(key)) |
||||
|
&& (foundKey==null || key.length()>foundKey.length())) |
||||
|
foundKey = key; |
||||
|
} |
||||
|
|
||||
|
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); |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
return uploadsCourses.get(foundKey); |
||||
|
} |
||||
|
|
||||
|
private static String normalizeGreekNumbers(String stringWithGreekNumbers) { |
||||
|
StringBuilder normalizedStrBuilder = new StringBuilder(stringWithGreekNumbers); |
||||
|
Pattern pattern = Pattern.compile("(Ι+)(?:\\s|\\(|\\)|$)"); |
||||
|
Matcher matcher = pattern.matcher(stringWithGreekNumbers); |
||||
|
while (matcher.find()) |
||||
|
normalizedStrBuilder.replace(matcher.start(1), matcher.end(1), matcher.group(1).replaceAll("Ι", "I")); |
||||
|
return normalizedStrBuilder.toString(); |
||||
|
} |
||||
|
} |
@ -0,0 +1,8 @@ |
|||||
|
package gr.thmmy.mthmmy.activities.upload.multipart; |
||||
|
|
||||
|
public class MultipartUploadException extends RuntimeException { |
||||
|
public MultipartUploadException(String message) { |
||||
|
super(message); |
||||
|
} |
||||
|
|
||||
|
} |
@ -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<MultipartUploadRequest> { |
||||
|
|
||||
|
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<? extends UploadTask> 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; |
||||
|
} |
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
@ -0,0 +1,45 @@ |
|||||
|
package gr.thmmy.mthmmy.model; |
||||
|
|
||||
|
import android.net.Uri; |
||||
|
|
||||
|
import androidx.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; |
||||
|
} |
||||
|
} |
@ -0,0 +1,233 @@ |
|||||
|
package gr.thmmy.mthmmy.services; |
||||
|
|
||||
|
import android.app.NotificationManager; |
||||
|
import android.content.Context; |
||||
|
import android.content.Intent; |
||||
|
import android.os.Build; |
||||
|
import android.os.Bundle; |
||||
|
import android.view.View; |
||||
|
import android.view.Window; |
||||
|
import android.widget.Button; |
||||
|
import android.widget.TextView; |
||||
|
import android.widget.Toast; |
||||
|
|
||||
|
import androidx.appcompat.app.AlertDialog; |
||||
|
|
||||
|
import com.snatik.storage.Storage; |
||||
|
|
||||
|
import net.gotev.uploadservice.ServerResponse; |
||||
|
import net.gotev.uploadservice.UploadInfo; |
||||
|
import net.gotev.uploadservice.UploadService; |
||||
|
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"; |
||||
|
|
||||
|
public static final String ACTION_COMBINED_UPLOAD = "ACTION_COMBINED_UPLOAD"; |
||||
|
public static final String ACTION_CANCEL_UPLOAD = "ACTION_CANCEL_UPLOAD"; |
||||
|
public static final String ACTION_RETRY_UPLOAD = "ACTION_RETRY_UPLOAD"; |
||||
|
|
||||
|
/*public static final String UPLOAD_RETRY_FILENAME = "UPLOAD_RETRY_FILENAME"; |
||||
|
public static final String UPLOAD_RETRY_CATEGORY = "UPLOAD_RETRY_CATEGORY"; |
||||
|
public static final String UPLOAD_RETRY_TITLE = "UPLOAD_RETRY_TITLE"; |
||||
|
public static final String UPLOAD_RETRY_DESCRIPTION = "UPLOAD_RETRY_DESCRIPTION"; |
||||
|
public static final String UPLOAD_RETRY_ICON = "UPLOAD_RETRY_ICON"; |
||||
|
public static final String UPLOAD_RETRY_UPLOADER = "UPLOAD_RETRY_UPLOADER"; |
||||
|
public static final String UPLOAD_RETRY_FILE_URI = "UPLOAD_RETRY_FILE_URI";*/ |
||||
|
|
||||
|
private Storage storage; |
||||
|
private static AlertDialog uploadProgressDialog; |
||||
|
private static String dialogUploadID; |
||||
|
//private static Intent multipartUploadRetryIntent;
|
||||
|
|
||||
|
@Override |
||||
|
public void onReceive(Context context, Intent intent) { |
||||
|
String intentAction = intent.getAction(); |
||||
|
Bundle intentBundle = intent.getExtras(); |
||||
|
if (intentAction == null || intentBundle == null) { |
||||
|
super.onReceive(context, intent); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
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: |
||||
|
String retryFilename = intentBundle.getString(UPLOAD_RETRY_FILENAME); |
||||
|
String retryCategory = intentBundle.getString(UPLOAD_RETRY_CATEGORY); |
||||
|
String retryTitleText = intentBundle.getString(UPLOAD_RETRY_TITLE); |
||||
|
String retryDescription = intentBundle.getString(UPLOAD_RETRY_DESCRIPTION); |
||||
|
String retryIcon = intentBundle.getString(UPLOAD_RETRY_ICON); |
||||
|
String retryUploaderProfile = intentBundle.getString(UPLOAD_RETRY_UPLOADER); |
||||
|
Uri retryFileUri = (Uri) intentBundle.get(UPLOAD_RETRY_FILE_URI); |
||||
|
String retryUploadID = UUID.randomUUID().toString(); |
||||
|
|
||||
|
UploadActivity.uploadFile(context, retryUploadID, |
||||
|
UploadActivity.getConfigForUpload(context, retryUploadID, retryFilename, retryCategory, |
||||
|
retryTitleText, retryDescription, retryIcon, retryUploaderProfile, retryFileUri), |
||||
|
retryCategory, retryTitleText, retryDescription, retryIcon, |
||||
|
retryUploaderProfile, retryFileUri); |
||||
|
|
||||
|
break;*/ |
||||
|
default: |
||||
|
super.onReceive(context, intent); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@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) { |
||||
|
Button alertDialogNeutral = uploadProgressDialog.getButton(AlertDialog.BUTTON_NEUTRAL); |
||||
|
alertDialogNeutral.setText(R.string.upload_resume_in_background); |
||||
|
alertDialogNeutral.setOnClickListener(v -> uploadProgressDialog.dismiss()); |
||||
|
|
||||
|
Button alertDialogNegative = uploadProgressDialog.getButton(AlertDialog.BUTTON_NEGATIVE); |
||||
|
alertDialogNegative.setText(R.string.cancel); |
||||
|
alertDialogNegative.setOnClickListener(v -> { |
||||
|
Timber.d("Cancelling upload (id: %s)", dialogUploadID); |
||||
|
UploadService.stopUpload(dialogUploadID); |
||||
|
uploadProgressDialog.dismiss(); |
||||
|
}); |
||||
|
|
||||
|
if (uploadProgressDialog.isShowing()) { |
||||
|
Window progressWindow = uploadProgressDialog.getWindow(); |
||||
|
if (progressWindow != null) { |
||||
|
MaterialProgressBar dialogProgressBar = progressWindow.findViewById(R.id.dialogProgressBar); |
||||
|
TextView dialogProgressText = progressWindow.findViewById(R.id.dialog_upload_progress_text); |
||||
|
|
||||
|
dialogProgressBar.setProgress(uploadInfo.getProgressPercent()); |
||||
|
dialogProgressText.setText(context.getResources().getString( |
||||
|
R.string.upload_progress_dialog_bytes_uploaded, |
||||
|
(float) uploadInfo.getUploadRate(), |
||||
|
(int) uploadInfo.getUploadedBytes() / 1000, |
||||
|
(int) uploadInfo.getTotalBytes() / 1000)); |
||||
|
} |
||||
|
|
||||
|
if (uploadInfo.getUploadedBytes() == uploadInfo.getTotalBytes()) { |
||||
|
uploadProgressDialog.dismiss(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@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) { |
||||
|
/*Button alertDialogNeutral = uploadProgressDialog.getButton(AlertDialog.BUTTON_NEUTRAL); |
||||
|
alertDialogNeutral.setText("Retry"); |
||||
|
alertDialogNeutral.setOnClickListener(v -> { |
||||
|
if (multipartUploadRetryIntent != null) { |
||||
|
context.sendBroadcast(multipartUploadRetryIntent); |
||||
|
} |
||||
|
uploadProgressDialog.dismiss(); |
||||
|
});*/ |
||||
|
|
||||
|
Button alertDialogNegative = uploadProgressDialog.getButton(AlertDialog.BUTTON_NEGATIVE); |
||||
|
alertDialogNegative.setText(R.string.cancel); |
||||
|
alertDialogNegative.setOnClickListener(v -> { |
||||
|
cancelNotification(context, uploadInfo.getNotificationID()); |
||||
|
UploadsHelper.deleteTempFiles(storage); |
||||
|
uploadProgressDialog.dismiss(); |
||||
|
}); |
||||
|
|
||||
|
if (uploadProgressDialog.isShowing()) { |
||||
|
Window progressWindow = uploadProgressDialog.getWindow(); |
||||
|
if (progressWindow != null) { |
||||
|
MaterialProgressBar dialogProgressBar = progressWindow.findViewById(R.id.dialogProgressBar); |
||||
|
TextView dialogProgressText = progressWindow.findViewById(R.id.dialog_upload_progress_text); |
||||
|
|
||||
|
dialogProgressBar.setVisibility(View.GONE); |
||||
|
dialogProgressText.setText(R.string.upload_failed); |
||||
|
} |
||||
|
|
||||
|
if (uploadInfo.getUploadedBytes() == uploadInfo.getTotalBytes()) { |
||||
|
uploadProgressDialog.dismiss(); |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
cancelNotification(context, uploadInfo.getNotificationID()); |
||||
|
Intent combinedActionsIntent = new Intent(UploadsReceiver.ACTION_COMBINED_UPLOAD); |
||||
|
combinedActionsIntent.putExtra(UploadsReceiver.UPLOAD_ID_KEY, uploadInfo.getUploadId()); |
||||
|
context.sendBroadcast(combinedActionsIntent); |
||||
|
} |
||||
|
|
||||
|
Toast.makeText(context.getApplicationContext(), R.string.upload_failed, Toast.LENGTH_SHORT).show(); |
||||
|
if (storage == null) { |
||||
|
storage = new Storage(context.getApplicationContext()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) { |
||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { |
||||
|
uploadProgressDialog = null; |
||||
|
dialogUploadID = null; |
||||
|
} |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
else { |
||||
|
MultipartUploadException multipartUploadException = new MultipartUploadException(response); |
||||
|
Timber.e(multipartUploadException); |
||||
|
onError(context,uploadInfo,serverResponse,multipartUploadException); |
||||
|
} |
||||
|
|
||||
|
if (storage == null) { |
||||
|
storage = new Storage(context.getApplicationContext()); |
||||
|
} |
||||
|
|
||||
|
UploadsHelper.deleteTempFiles(storage); |
||||
|
} |
||||
|
|
||||
|
@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_cancelled, Toast.LENGTH_SHORT).show(); |
||||
|
if (storage == null) |
||||
|
storage = new Storage(context.getApplicationContext()); |
||||
|
|
||||
|
//cancelNotification(context, uploadInfo.getNotificationID());
|
||||
|
UploadsHelper.deleteTempFiles(storage); |
||||
|
} |
||||
|
|
||||
|
public static void setDialogDisplay(AlertDialog uploadProgressDialog, String dialogUploadID, |
||||
|
Intent multipartUploadRetryIntent) { |
||||
|
UploadsReceiver.uploadProgressDialog = uploadProgressDialog; |
||||
|
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); |
||||
|
} |
||||
|
} |
@ -0,0 +1,173 @@ |
|||||
|
package gr.thmmy.mthmmy.utils; |
||||
|
|
||||
|
import android.content.ContentResolver; |
||||
|
import android.content.ContentValues; |
||||
|
import android.content.Context; |
||||
|
import android.content.Intent; |
||||
|
import android.content.pm.PackageManager; |
||||
|
import android.content.pm.ResolveInfo; |
||||
|
import android.content.res.AssetFileDescriptor; |
||||
|
import android.graphics.Bitmap; |
||||
|
import android.graphics.BitmapFactory; |
||||
|
import android.graphics.Matrix; |
||||
|
import android.net.Uri; |
||||
|
import android.os.Environment; |
||||
|
import android.provider.MediaStore; |
||||
|
import android.widget.Toast; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
import androidx.annotation.Nullable; |
||||
|
import androidx.core.content.FileProvider; |
||||
|
import androidx.exifinterface.media.ExifInterface; |
||||
|
|
||||
|
import java.io.File; |
||||
|
import java.io.FileNotFoundException; |
||||
|
import java.io.FileOutputStream; |
||||
|
import java.text.SimpleDateFormat; |
||||
|
import java.util.Date; |
||||
|
import java.util.List; |
||||
|
import java.util.Locale; |
||||
|
|
||||
|
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) { |
||||
|
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); |
||||
|
//Ensures that there's a camera activity to handle the intent
|
||||
|
if (takePictureIntent.resolveActivity(context.getPackageManager()) != null) { |
||||
|
Uri photoURI = FileProvider.getUriForFile(context, context.getPackageName() + |
||||
|
".provider", photoFile); |
||||
|
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); |
||||
|
|
||||
|
//Grants necessary permissions for Gallery to use the Uri
|
||||
|
List<ResolveInfo> resInfoList = context.getPackageManager(). |
||||
|
queryIntentActivities(takePictureIntent, PackageManager.MATCH_DEFAULT_ONLY); |
||||
|
for (ResolveInfo resolveInfo : resInfoList) { |
||||
|
String packageName = resolveInfo.activityInfo.packageName; |
||||
|
context.grantUriPermission(packageName, photoURI, |
||||
|
Intent.FLAG_GRANT_WRITE_URI_PERMISSION | |
||||
|
Intent.FLAG_GRANT_READ_URI_PERMISSION); |
||||
|
} |
||||
|
return takePictureIntent; |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public static Uri processResult(Context context, File photoFile) { |
||||
|
Bitmap bitmap; |
||||
|
Uri fileUri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", photoFile); |
||||
|
|
||||
|
bitmap = getImageResized(context, fileUri); |
||||
|
int rotation = getRotation(context, fileUri); |
||||
|
bitmap = rotate(bitmap, rotation); |
||||
|
|
||||
|
try { |
||||
|
FileOutputStream out = new FileOutputStream(photoFile); |
||||
|
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out); |
||||
|
out.flush(); |
||||
|
out.close(); |
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
|
||||
|
return fileUri; |
||||
|
} |
||||
|
|
||||
|
@Nullable |
||||
|
public static File createImageFile(Context context) { |
||||
|
// Create an image file name
|
||||
|
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.FRANCE).format(new Date()); |
||||
|
String imageFileName = "mTHMMY_" + timeStamp + ".jpg"; |
||||
|
|
||||
|
File imageFolder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + |
||||
|
File.separator + "mTHMMY"); |
||||
|
|
||||
|
if (!imageFolder.exists()&&!imageFolder.mkdirs()) { |
||||
|
Timber.w("Photos folder build returned false in %s", TakePhoto.class.getSimpleName()); |
||||
|
Toast.makeText(context, "Couldn't create photos directory", Toast.LENGTH_SHORT).show(); |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
return new File(imageFolder, imageFileName); |
||||
|
} |
||||
|
|
||||
|
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, 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()); |
||||
|
|
||||
|
ContentResolver cr = context.getContentResolver(); |
||||
|
cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); |
||||
|
} |
||||
|
|
||||
|
private static Bitmap getImageResized(Context context, Uri selectedImage) { |
||||
|
Bitmap bm; |
||||
|
int[] sampleSizes = new int[]{5, 3, 2, 1}; |
||||
|
int i = 0; |
||||
|
do { |
||||
|
bm = decodeBitmap(context, selectedImage, sampleSizes[i]); |
||||
|
i++; |
||||
|
} while (bm.getWidth() < DEFAULT_MIN_WIDTH_QUALITY && i < sampleSizes.length); |
||||
|
return bm; |
||||
|
} |
||||
|
|
||||
|
private static Bitmap decodeBitmap(Context context, Uri theUri, int sampleSize) { |
||||
|
BitmapFactory.Options options = new BitmapFactory.Options(); |
||||
|
options.inSampleSize = sampleSize; |
||||
|
|
||||
|
AssetFileDescriptor fileDescriptor = null; |
||||
|
try { |
||||
|
fileDescriptor = context.getContentResolver().openAssetFileDescriptor(theUri, "r"); |
||||
|
} catch (FileNotFoundException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
|
||||
|
assert fileDescriptor != null; |
||||
|
return BitmapFactory.decodeFileDescriptor( |
||||
|
fileDescriptor.getFileDescriptor(), null, options); |
||||
|
} |
||||
|
|
||||
|
private static int getRotation(Context context, Uri imageUri) { |
||||
|
int rotation = 0; |
||||
|
try { |
||||
|
|
||||
|
context.getContentResolver().notifyChange(imageUri, null); |
||||
|
ExifInterface exif = new ExifInterface(imageUri.getPath()); |
||||
|
int orientation = exif.getAttributeInt( |
||||
|
ExifInterface.TAG_ORIENTATION, |
||||
|
ExifInterface.ORIENTATION_NORMAL); |
||||
|
|
||||
|
switch (orientation) { |
||||
|
case ExifInterface.ORIENTATION_ROTATE_270: |
||||
|
rotation = 270; |
||||
|
break; |
||||
|
case ExifInterface.ORIENTATION_ROTATE_180: |
||||
|
rotation = 180; |
||||
|
break; |
||||
|
case ExifInterface.ORIENTATION_ROTATE_90: |
||||
|
rotation = 90; |
||||
|
break; |
||||
|
} |
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
return rotation; |
||||
|
} |
||||
|
|
||||
|
private static Bitmap rotate(Bitmap bm, int rotation) { |
||||
|
if (rotation != 0) { |
||||
|
Matrix matrix = new Matrix(); |
||||
|
matrix.postRotate(rotation); |
||||
|
return Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true); |
||||
|
} |
||||
|
return bm; |
||||
|
} |
||||
|
} |
@ -0,0 +1,27 @@ |
|||||
|
package gr.thmmy.mthmmy.utils; |
||||
|
import android.content.Context; |
||||
|
import android.util.AttributeSet; |
||||
|
|
||||
|
import androidx.appcompat.widget.AppCompatButton; |
||||
|
|
||||
|
public class ToggledBackgroundButton extends AppCompatButton { |
||||
|
|
||||
|
public ToggledBackgroundButton(Context context) { |
||||
|
super(context); |
||||
|
} |
||||
|
|
||||
|
public ToggledBackgroundButton(Context context, AttributeSet attrs) { |
||||
|
super(context, attrs); |
||||
|
} |
||||
|
|
||||
|
public ToggledBackgroundButton(Context context, AttributeSet attrs, int defStyleAttr) { |
||||
|
super(context, attrs, defStyleAttr); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void setEnabled(boolean enabled) { |
||||
|
setAlpha(enabled ? 1 : 0.5f); |
||||
|
super.setEnabled(enabled); |
||||
|
} |
||||
|
} |
||||
|
|
@ -1,4 +0,0 @@ |
|||||
<?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> |
|
@ -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="#26A69A" android:pathData="M19,8l-4,4h3c0,3.31 -2.69,6 -6,6 -1.01,0 -1.97,-0.25 -2.8,-0.7l-1.46,1.46C8.97,19.54 10.43,20 12,20c4.42,0 8,-3.58 8,-8h3l-4,-4zM6,12c0,-3.31 2.69,-6 6,-6 1.01,0 1.97,0.25 2.8,0.7l1.46,-1.46C15.03,4.46 13.57,4 12,4c-4.42,0 -8,3.58 -8,8H1l4,4 4,-4H6z"/> |
||||
|
</vector> |
@ -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="#26A69A" android:pathData="M12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2zM17,15.59L15.59,17 12,13.41 8.41,17 7,15.59 10.59,12 7,8.41 8.41,7 12,10.59 15.59,7 17,8.41 13.41,12 17,15.59z"/> |
||||
|
</vector> |
@ -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="#FF9800" android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/> |
||||
|
</vector> |
@ -0,0 +1,24 @@ |
|||||
|
<?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"> |
||||
|
|
||||
|
<androidx.appcompat.widget.AppCompatTextView |
||||
|
android:id="@+id/upload_file_item_text" |
||||
|
android:layout_width="0dp" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:layout_gravity="center" |
||||
|
android:layout_weight="1" |
||||
|
android:ellipsize="marquee" |
||||
|
android:singleLine="true" |
||||
|
android:textColor="@color/primary_text" /> |
||||
|
|
||||
|
<androidx.appcompat.widget.AppCompatImageButton |
||||
|
android:id="@+id/upload_file_item_remove" |
||||
|
android:layout_width="wrap_content" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:theme="@style/LightBackgroundColoredButton" |
||||
|
app:srcCompat="@drawable/ic_delete_accent_24dp" /> |
||||
|
</LinearLayout> |
@ -0,0 +1,10 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android" |
||||
|
android:id="@+id/upload_filename_info_text" |
||||
|
android:layout_width="wrap_content" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:background="@color/primary_light" |
||||
|
android:linksClickable="true" |
||||
|
android:padding="8dp" |
||||
|
android:text="@string/upload_filename_info" |
||||
|
android:textColor="@color/primary_text" /> |
@ -0,0 +1,43 @@ |
|||||
|
<?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="match_parent" |
||||
|
android:orientation="vertical" |
||||
|
android:paddingEnd="24dp" |
||||
|
android:paddingStart="24dp"> |
||||
|
|
||||
|
<TextView |
||||
|
android:id="@+id/dialog_title" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:layout_marginTop="24dp" |
||||
|
android:layout_marginBottom="5dp" |
||||
|
android:text="@string/upload_progress_dialog_title" |
||||
|
android:textColor="@color/accent" |
||||
|
android:textSize="20sp" /> |
||||
|
|
||||
|
<View |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="1dp" |
||||
|
android:layout_marginBottom="15dp" |
||||
|
android:background="@color/secondary_text" /> |
||||
|
|
||||
|
<me.zhanghai.android.materialprogressbar.MaterialProgressBar |
||||
|
android:id="@+id/dialogProgressBar" |
||||
|
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="@dimen/progress_bar_height" |
||||
|
android:indeterminate="false" |
||||
|
app:mpb_progressStyle="horizontal" |
||||
|
app:mpb_progressTint="@color/accent" /> |
||||
|
|
||||
|
<TextView |
||||
|
android:id="@+id/dialog_upload_progress_text" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:layout_marginBottom="20dp" |
||||
|
android:layout_marginTop="12dp" |
||||
|
android:minEms="64" |
||||
|
android:textColor="@color/white" /> |
||||
|
</LinearLayout> |
@ -0,0 +1,158 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<resources> |
||||
|
<!--Format: Original:Minified:Greeklish--> |
||||
|
<string-array name="string_array_uploads_courses"> |
||||
|
<item>Ακουστική I:Ακουστική 1:Akoustiki_I</item> |
||||
|
<item>Ακουστική II:Ακουστική 2:Akoustiki_II</item> |
||||
|
<item>Ανάλυση Ηλεκτρικών Κυκλωμάτων με Υπολογιστή:Ανάλυση Ηλεκτρικ. Κυκλ. με Υπολογιστή:Analysi_Ilektr_Kykl</item> |
||||
|
<item>Ανάλυση Συστημάτων Ηλεκτρικής Ενέργειας:ΑΣΗΕ:ASHE</item> |
||||
|
<item>Ανάλυση Χρονοσειρών:Χρονοσειρές:Xronoseires</item> |
||||
|
<item>Ανάλυση και Σχεδίαση Αλγορίθμων:Αλγόριθμοι:Algorithms</item> |
||||
|
<item>Αναγνώριση Προτύπων:Αναγνώριση Προτύπων:protipa</item> |
||||
|
<item>Αναλογικές Τηλεπικοινωνίες (πρώην Τηλεπικοινωνιακά Συστήματα I):Αναλογικές Τηλεπ.:Anal_Tilep</item> |
||||
|
<item>Αντικειμενοστραφής Προγραμματισμός:Αντικειμενοστραφής:OOP</item> |
||||
|
<item>Αξιοπιστία Συστημάτων:Αξιοπιστία Συστημάτων:Aksiopistia_Systimaton</item> |
||||
|
<item>Αριθμητική Ανάλυση:Αριθμ. Ανάλυση:Arith_Anal</item> |
||||
|
<item>Αρχές Οικονομίας:Αρχές Οικονομίας:Arx_Oikonomias</item> |
||||
|
<item>Αρχές Παράλληλης Επεξεργασίας:Αρχές Παράλληλης Επεξεργασίας:Arxes_Parall_Epeksergasias</item> |
||||
|
<item>Αρχιτεκτονική Υπολογιστών:Αρχ. Υπολογιστών:Arx_Ypologiston</item> |
||||
|
<item>Ασαφή Συστήματα:Ασαφή:Asafi</item> |
||||
|
<item>Ασφάλεια Πληροφοριακών Συστημάτων:Ασφάλεια:Asfaleia</item> |
||||
|
<item>Ασύρματος Τηλεπικοινωνία I:Ασύρματος 1:Asyrmatos_I</item> |
||||
|
<item>Ασύρματος Τηλεπικοινωνία II:Ασύρματος 2:Asyrmatos_II</item> |
||||
|
<item>Βάσεις Δεδομένων:Βάσεις:Vaseis</item> |
||||
|
<item>Βιομηχανικά Ηλεκτρονικά:Βιομηχανικά Ηλεκτρονικά:Viomix_Ilektronika</item> |
||||
|
<item>Βιομηχανική Πληροφορική:Βιομηχανική Πληρ:Viomix_Plir</item> |
||||
|
<item>Βιοϊατρική Τεχνολογία:Βιοιατρική:Vioiatriki</item> |
||||
|
<item>Γεωηλεκτρομαγνητισμός:Γεωηλεκτρομαγνητισμός:Geoilektromagnitismos</item> |
||||
|
<item>Γραμμική Άλγεβρα:Γραμμ. Άλγεβρ.:Grammiki_Algevra</item> |
||||
|
<item>Γραφική με Υπολογιστές:Γραφική:Grafiki</item> |
||||
|
<item>Δίκτυα Τηλεπικοινωνιών:Δίκτυα Τηλέπ.:Diktya_Tilep</item> |
||||
|
<item>Δίκτυα Υπολογιστών I:Δίκτυα 1:Diktya_I</item> |
||||
|
<item>Δίκτυα Υπολογιστών II:Δίκτυα 2:Diktya_II</item> |
||||
|
<item>Διάδοση Η/Μ Κύματος II:Διάδοση 2:Diadosi_II</item> |
||||
|
<item>Διάδοση Ηλεκτρομαγνητικού Κύματος I (πρώην Πεδίο III):Διάδοση 1:Diadosi_I</item> |
||||
|
<item>Διακριτά Μαθηματικά:Διακριτά Μαθηματικά:Diakrita</item> |
||||
|
<item>Διακριτά μαθηματικά:Διακριτά Μαθηματικά:Diakrita</item> |
||||
|
<item>Διανεμημένη Παραγωγή:Διανεμημένη Παραγωγή:Dian_Paragogi</item> |
||||
|
<item>Διατάξεις Υψηλών Συχνοτήτων:ΔΥΣ:DYS</item> |
||||
|
<item>Διαφορικές Εξισώσεις:Διαφορικές:Diaforikes</item> |
||||
|
<item>Διαχείριση Συστημάτων Ηλεκτρικής Ενέργειας:ΔΣΗΕ:DSHE</item> |
||||
|
<item>Δομές Δεδομένων:Δομ. Δεδομ.:Domes_Dedomenon</item> |
||||
|
<item>Δομημένος Προγραμματισμός:Δομ. Προγραμμ.:C</item> |
||||
|
<item>Ειδικά Κεφάλαια Διαφορικών Εξισώσεων:Ειδικά Κεφάλαια Διαφορικών Εξισώσεων:Eidika_Kef_Diaf_Eksis</item> |
||||
|
<item>Ειδικά Κεφάλαια Ηλεκτρομαγνητικού Πεδίου I:Ειδικά Κεφάλαια Ηλεκτρομαγνητικού Πεδίου I:Eidika_Kef_HM_Pediou_I</item> |
||||
|
<item>Ειδικά Κεφάλαια Συστημάτων Ηλεκτρικής Ενέργειας:ΕΚΣΗΕ:EKSHE</item> |
||||
|
<item>Ειδικές Αρχιτεκτονικές Υπολογιστών:Ειδικές Αρχιτεκτονικές Υπολογιστών:Eidikes_Arx_Ypolog</item> |
||||
|
<item>Ειδικές Κεραίες, Σύνθεση Κεραιών:Ειδικές Κεραίες, Σύνθεση Κεραιών:Eidikes_Keraies</item> |
||||
|
<item>Εισαγωγή στην Ενεργειακή Τεχνολογία I:ΕΕΤ 1:EET_I</item> |
||||
|
<item>Εισαγωγή στην Ενεργειακή Τεχνολογία II:ΕΕΤ2:EET_II</item> |
||||
|
<item>Εισαγωγή στην Πολιτική Οικονομία:Πολιτική Οικονομία:Polit_Oik</item> |
||||
|
<item>Εισαγωγή στις εφαρμογές Πυρηνικής Τεχνολογίας:Εισ. Πυρηνικη Τεχν.:Intro_Pyriniki_Texn</item> |
||||
|
<item>Ενσωματωμένα Συστήματα Πραγματικού Χρόνου:Ενσωματωμένα:Enswmatwmena</item> |
||||
|
<item>Επιχειρησιακή Έρευνα:Επιχειρησιακή Έρευνα:Epixeirisiaki</item> |
||||
|
<item>Ευρυζωνικά Δίκτυα:Ευρυζωνικά:Evryzonika</item> |
||||
|
<item>Ευφυή Συστήματα Ρομπότ:Ευφυή:eufuh</item> |
||||
|
<item>Εφαρμογές Τηλεπικοινωνιακών Διατάξεων:Εφαρμογές Τηλεπ. Διατάξεων:Efarm_Tilep_Diatakseon</item> |
||||
|
<item>Εφαρμοσμένα Μαθηματικά I:Εφαρμοσμένα 1:Efarmosmena_Math_I</item> |
||||
|
<item>Εφαρμοσμένα Μαθηματικά II:Εφαρμοσμένα 2:Efarmosmena_Math_II</item> |
||||
|
<item>Εφαρμοσμένη Θερμοδυναμική:Θερμοδυναμική:Thermodynamiki</item> |
||||
|
<item>Ηλεκτρακουστική I:Ηλεκτρακουστική 1:Ilektrakoustiki_I</item> |
||||
|
<item>Ηλεκτρακουστική II:Ηλεκτρακουστική 2:Ilektrakoustiki_II</item> |
||||
|
<item>Ηλεκτρικά Κυκλώματα I:Κυκλώματα 1:Kyklomata_I</item> |
||||
|
<item>Ηλεκτρικά Κυκλώματα II:Κυκλώματα 2:Kyklomata_II</item> |
||||
|
<item>Ηλεκτρικά Κυκλώματα III:Κυκλώματα 3:Kyklomata_I</item> |
||||
|
<item>Ηλεκτρικές Μετρήσεις I:Μετρήσεις 1:Metriseis_I</item> |
||||
|
<item>Ηλεκτρικές Μετρήσεις II:Μετρήσεις 2:Metriseis_II</item> |
||||
|
<item>Ηλεκτρικές Μηχανές I:Μηχανές I:Mixanes_I</item> |
||||
|
<item>Ηλεκτρικές Μηχανές Α\':Μηχανές Α:Mixanes_A</item> |
||||
|
<item>Ηλεκτρικές Μηχανές Β\':Μηχανές Β:Mixanes_B</item> |
||||
|
<item>Ηλεκτρικές Μηχανές Γ\':Μηχανές Γ:Mixanes_C</item> |
||||
|
<item>Ηλεκτρική Οικονομία:Ηλεκτρική Οικονομία:Ilektr_Oikonomia</item> |
||||
|
<item>Ηλεκτρολογικά Υλικά:Ηλεκτρ. Υλικά:Ylika</item> |
||||
|
<item>Ηλεκτρομαγνητική Συμβατότητα:H/M Συμβατότητα:HM_Symvatotita</item> |
||||
|
<item>Ηλεκτρομαγνητικό Πεδίο I:Πεδίο 1:Pedio_I</item> |
||||
|
<item>Ηλεκτρομαγνητικό Πεδίο II:Πεδίο 2:Pedio_II</item> |
||||
|
<item>Ηλεκτρονικά Ισχύος I:Ισχύος 1:Isxyos_I</item> |
||||
|
<item>Ηλεκτρονικά Ισχύος II:Ισχύος 2:Isxyos_II</item> |
||||
|
<item>Ηλεκτρονικές Διατάξεις και Μετρήσεις:Ηλεκτρονικές Διατάξεις και Μετρήσεις:Ilektron_Diatakseis_Metriseis</item> |
||||
|
<item>Ηλεκτρονική I:Ηλεκτρονική 1:Ilektroniki_I</item> |
||||
|
<item>Ηλεκτρονική II:Ηλεκτρονική 2:Ilektroniki_II</item> |
||||
|
<item>Ηλεκτρονική III:Ηλεκτρονική 3:Ilektroniki_III</item> |
||||
|
<item>Ημιαγωγά Υλικά: Θεωρία-Διατάξεις:Ημιαγωγά Υλικά:Imiagoga_Ylika</item> |
||||
|
<item>Θεωρία Πιθανοτήτων και Στατιστική:Πιθανότητες:Pithanotites</item> |
||||
|
<item>Θεωρία Πληροφοριών:Θεωρία Πληρ.:Theoria_Plir</item> |
||||
|
<item>Θεωρία Σημάτων και Γραμμικών Συστημάτων:Σήματα & Συστήματα:Analog_Sima</item> |
||||
|
<item>Θεωρία Σκέδασης:Σκέδαση:Skedasi</item> |
||||
|
<item>Θεωρία Υπολογισμών και Αλγορίθμων:ΘΥΑ:THYA</item> |
||||
|
<item>Θεωρία και Τεχνολογία Πυρηνικών Αντιδραστήρων:Τεχνολογία Αντιδραστήρων:Texn_Antidrasthron</item> |
||||
|
<item>Κβαντική Φυσική:Κβαντική:Kvantiki</item> |
||||
|
<item>Κινητές και Δορυφορικές Επικοινωνίες:Κινητές & Δορυφορικές Επικοινωνίες:Kinites_Doryforikes_Epik</item> |
||||
|
<item>Λειτουργικά Συστήματα:Λειτουργικά:OS</item> |
||||
|
<item>Λογική Σχεδίαση:Λογική Σχεδίαση:Logiki_Sxediasi</item> |
||||
|
<item>Λογισμός I:Λογισμός 1:Logismos_I</item> |
||||
|
<item>Λογισμός II:Λογισμός 2:Logismos_II</item> |
||||
|
<item>Μετάδοση Θερμότητας:Μετάδοση Θερμ.:Metadosi_Therm</item> |
||||
|
<item>Μικροεπεξεργαστές και Περιφερειακά:Μίκρο 2:Mikro_II</item> |
||||
|
<item>Μικροκυματική Τηλεπισκόπηση:Τηλεπισκόπηση:Tilepiskopisi</item> |
||||
|
<item>Μικροκύματα I:Μικροκύματα 1:Mikrokymata_I</item> |
||||
|
<item>Μικροκύματα II:Μικροκύματα 2:Mikrokymata_II</item> |
||||
|
<item>Οπτικές Επικοινωνίες:Οπτικές Τηλεπ.:Optikes_Tilep</item> |
||||
|
<item>Οπτική I:Οπτική 1:Optiki_I</item> |
||||
|
<item>Οπτική II:Οπτική 2:Optiki_II</item> |
||||
|
<item>Οργάνωση Υπολογιστών:Οργάνωση Υπολ.:Org_Ypol</item> |
||||
|
<item>Οργάνωση και Διοίκηση Εργοστασίων:Οργάνωση και Διοίκηση Εργοστασίων:Organ_Dioik_Ergostasion</item> |
||||
|
<item>Παράλληλα και Κατανεμημένα Συστήματα:Παράλληλα:Parallila</item> |
||||
|
<item>Προγραμματιζόμενα Κυκλώματα ASIC:ASIC:ASIC</item> |
||||
|
<item>Προγραμματιστικές Τεχνικές:Προγραμματ. Τεχν.:CPP</item> |
||||
|
<item>Προηγμένες Τεχνικές Επεξεργασίας Σήματος:ΠΤΕΣ:PTES</item> |
||||
|
<item>Προσομοίωση και Μοντελοποίηση Συστημάτων:Μοντελοποίηση:Montelopoiisi</item> |
||||
|
<item>Ρομποτική:Ρομποτική:Robotiki</item> |
||||
|
<item>Σήματα και Συστήματα:Σήματα & Συστήματα:Analog_Sima</item> |
||||
|
<item>Σερβοκινητήρια Συστήματα:Σέρβο:Servo</item> |
||||
|
<item>Σταθμοί Παραγωγής Ηλεκτρικής Ενέργειας:ΣΠΗΕ:SPHE</item> |
||||
|
<item>Στοχαστικά Σήματα και Διαδικασίες:Στοχαστικό:Stochastic</item> |
||||
|
<item>Στοχαστικό Σήμα:Στοχαστικό:Stochastic</item> |
||||
|
<item>Συστήματα Αυτομάτου Ελέγχου I:ΣΑΕ 1:SAE_I</item> |
||||
|
<item>Συστήματα Αυτομάτου Ελέγχου II:ΣΑΕ 2:SAE_II</item> |
||||
|
<item>Συστήματα Αυτομάτου Ελέγχου III:ΣΑΕ 3:SAE_III</item> |
||||
|
<item>Συστήματα Ηλεκτρικής Ενέργειας I:ΣΗΕ 1:SHE_I</item> |
||||
|
<item>Συστήματα Ηλεκτρικής Ενέργειας II:ΣΗΕ 2:SHE_II</item> |
||||
|
<item>Συστήματα Ηλεκτρικής Ενέργειας III:ΣΗΕ 3:SHE_III</item> |
||||
|
<item>Συστήματα Ηλεκτροκίνησης:Ηλεκτροκίνηση:Ilektrokinisi</item> |
||||
|
<item>Συστήματα Μικροϋπολογιστών:Μίκρο 1:Mikro_I</item> |
||||
|
<item>Συστήματα Πολυμέσων και Εικονική Πραγματικότητα:Πολυμέσα:Polymesa</item> |
||||
|
<item>Συστήματα Υπολογιστών (Υπολογιστικά Συστήματα):Συσ. Υπολογιστών:Sys_Ypologiston</item> |
||||
|
<item>Σχεδίαση Συστημάτων VLSI:VLSI:VLSI</item> |
||||
|
<item>Σύνθεση Ενεργών και Παθητικών Κυκλωμάτων:Σύνθεση:Synthesi</item> |
||||
|
<item>Σύνθεση Τηλεπικοινωνιακών Διατάξεων:Σύνθεση Τηλεπ. Διατάξεων:Synth_Tilep_Diatakseon</item> |
||||
|
<item>Τεχνικές Βελτιστοποίησης:Βελτιστοποίηση:Veltistopoiisi</item> |
||||
|
<item>Τεχνικές Κωδικοποίησης:Τεχνικές Κωδικοποίησης:Texn_Kodikopoiisis</item> |
||||
|
<item>Τεχνικές Σχεδίασης με Η/Υ:Σχέδιο:sxedio</item> |
||||
|
<item>Τεχνικές μη Καταστρεπτικών Δοκιμών:Μη Καταστρεπτικές Δοκιμές:Non_Destructive_Tests</item> |
||||
|
<item>Τεχνική Μηχανική:Τεχν. Μηχαν.:Texn_Mixan</item> |
||||
|
<item>Τεχνολογία Ήχου και Εικόνας:Τεχνολογία Ήχου και Εικόνας:Texn_Ixou_Eikonas</item> |
||||
|
<item>Τεχνολογία Ηλεκτροτεχνικών Υλικών:Ηλεκτροτεχνικά Υλικά:Ilektrotexnika_Ylika</item> |
||||
|
<item>Τεχνολογία Λογισμικού:Τεχνολογία Λογισμικού:SE</item> |
||||
|
<item>Τηλεοπτικά Συστήματα:Τηλεοπτικά:Tileoptika</item> |
||||
|
<item>Τηλεπικοινωνιακά Συστήματα I:Τηλεπικοινωνιακά I:Tilepikoinoniaka_I</item> |
||||
|
<item>Τηλεπικοινωνιακά Συστήματα II:Τηλεπικοινωνιακά II:Tilepikoinoniaka_II</item> |
||||
|
<item>Τηλεπικοινωνιακή Ηλεκτρονική:Τηλεπ. Ηλεκτρ.:Tilep_Ilektr</item> |
||||
|
<item>Υπολογιστικές Μέθοδοι στα Ενεργειακά Συστήματα:ΥΜΕΣ:YMES</item> |
||||
|
<item>Υπολογιστικός Ηλεκτρομαγνητισμός:Υπολογιστικός Η/Μ:Ypologistikos_HM</item> |
||||
|
<item>Υψηλές Τάσεις I:Υψηλές 1:Ypsiles_I</item> |
||||
|
<item>Υψηλές Τάσεις II:Υψηλές 2:Ypsiles_II</item> |
||||
|
<item>Υψηλές Τάσεις III:Υψηλές 3:Ypsiles_III</item> |
||||
|
<item>Υψηλές Τάσεις 4:Υψηλές 4:Ypsiles_IV</item> |
||||
|
<item>Φυσική I:Φυσική 1:Fysiki_I</item> |
||||
|
<item>Φωτονική Τεχνολογία:Φωτονική:Fotoniki</item> |
||||
|
<item>Ψηφιακά Συστήματα I:Ψηφιακά 1:Psifiaka_I</item> |
||||
|
<item>Ψηφιακά Συστήματα II:Ψηφιακά 2:Psifiaka_II</item> |
||||
|
<item>Ψηφιακά Συστήματα III:Ψηφιακά 3:Psifiaka_III</item> |
||||
|
<item>Ψηφιακά Φίλτρα:Φίλτρα:Filtra</item> |
||||
|
<item>Ψηφιακές Τηλεπικοινωνίες I:Ψηφιακές Τηλεπ. 1:Psif_Tilep_I</item> |
||||
|
<item>Ψηφιακές Τηλεπικοινωνίες II:Ψηφιακές Τηλεπ. 2:Psif_Tilep_II</item> |
||||
|
<item>Ψηφιακή Επεξεργασία Εικόνας:ΨΕΕ:PSEE</item> |
||||
|
<item>Ψηφιακή Επεξεργασία Σήματος:ΨΕΣ:PSES</item> |
||||
|
</string-array> |
||||
|
</resources> |
@ -1,6 +1,6 @@ |
|||||
#Sat Feb 09 12:35:50 EET 2019 |
#Tue Sep 17 12:32:34 EEST 2019 |
||||
distributionBase=GRADLE_USER_HOME |
distributionBase=GRADLE_USER_HOME |
||||
distributionPath=wrapper/dists |
distributionPath=wrapper/dists |
||||
zipStoreBase=GRADLE_USER_HOME |
zipStoreBase=GRADLE_USER_HOME |
||||
zipStorePath=wrapper/dists |
zipStorePath=wrapper/dists |
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip |
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip |
||||
|
Loading…
Reference in new issue