diff --git a/.idea/misc.xml b/.idea/misc.xml
index 9efabab..f4f18d3 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,8 +3,11 @@
@@ -52,7 +55,7 @@
-
+
diff --git a/app/build.gradle b/app/build.gradle
index a95302c..27c226f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -8,7 +8,7 @@ android {
minSdkVersion 24
targetSdkVersion 30
versionCode 1
- versionName "1.0"
+ versionName "2.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bfa73f6..0414bfa 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,20 +3,25 @@
package="com.localtransfer">
-
+
-
-
+ android:theme="@style/AppTheme">
+
+
-
-
+ android:label="@string/title_activity_settings">
-
+
-
+
+
-
+
+
-
diff --git a/app/src/main/java/com/localtransfer/DownloadFile.java b/app/src/main/java/com/localtransfer/DownloadFile.java
new file mode 100644
index 0000000..42fe433
--- /dev/null
+++ b/app/src/main/java/com/localtransfer/DownloadFile.java
@@ -0,0 +1,289 @@
+package com.localtransfer;
+
+import android.animation.ObjectAnimator;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.util.Log;
+import android.view.animation.Animation;
+import android.view.animation.LinearInterpolator;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import androidx.core.content.FileProvider;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.sql.Timestamp;
+
+public class DownloadFile extends Transfer {
+
+ public String href;
+
+ public String mime;
+
+ public String type;
+
+ public Uri uri;
+
+ private Button button;
+
+ public DownloadFile(Integer id) {
+ this.id = id;
+ instances.add(this);
+ info = "Download complete";
+ state = STATE_NOT_REQUESTED;
+ drawable = R.drawable.ic_download_24;
+ }
+
+ @Override
+ public void startTransfer() {
+ super.startTransfer();
+
+ startedTime = new Timestamp(System.currentTimeMillis());
+
+ state = STATE_RUNNING;
+
+ buttonProgressStart();
+
+ if (uri == null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
+ ContentValues values = new ContentValues();
+ values.put(MediaStore.MediaColumns.DISPLAY_NAME, name);
+ values.put(MediaStore.MediaColumns.MIME_TYPE, mime);
+ values.put(MediaStore.MediaColumns.RELATIVE_PATH, Transfer.shared_storage);
+ uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values);
+ }
+ try {
+ downloadFile();
+ } catch (IOException | NullPointerException e) {
+ final String ExceptionName = e.getClass().getSimpleName();
+ final String ExceptionMess = e.getMessage();
+ e.printStackTrace();
+
+ state = Transfer.STATE_FAILED;
+ progressEnd();
+ buttonProgressEnd();
+
+ if(ExceptionName != null && ExceptionMess != null) {
+ errorSnackbar(ExceptionName + ": " + ExceptionMess);
+ }
+
+ }
+ }
+
+ public boolean exist(Context context) {
+ if (!Transfer.use_shared_storage){
+ File file = new File(activity.getFilesDir(), name);
+
+ uri = FileProvider.getUriForFile(activity, activity.getPackageName(), file);
+
+ if (file.exists() && file.length() == size)
+ return true;
+ }
+ else {
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
+ Cursor cursor = context.getContentResolver().query(MediaStore.Downloads.EXTERNAL_CONTENT_URI, null, null, null, null);
+ while (cursor.moveToNext()) {
+ String MediaStore_File_name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Downloads.DISPLAY_NAME));
+ long MediaStore_File_size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Downloads.SIZE));
+ if(MediaStore_File_name.equals(name) && MediaStore_File_size == size) {
+ int cursor_id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID));
+ uri = ContentUris.withAppendedId(MediaStore.Downloads.EXTERNAL_CONTENT_URI, cursor_id);
+ return true;
+ }
+ }
+ }
+ else {
+ String save_location = null;
+ if (mime.equals("text/plain"))
+ save_location = context.getCacheDir().toString();
+ else
+ save_location = Environment.getExternalStorageDirectory() + "/" + Transfer.shared_storage;
+ new File(save_location).mkdirs();
+ File file = new File(save_location, name);
+ try {
+ file.createNewFile();
+ } catch (IOException e) {
+ final String ExceptionName = e.getClass().getSimpleName();
+ final String ExceptionMess = e.getMessage();
+ e.printStackTrace();
+
+ if(ExceptionName != null && ExceptionMess != null) {
+ errorSnackbar(ExceptionName + ": " + ExceptionMess);
+ }
+ }
+ uri = Uri.fromFile(file);
+ if (file.exists() && file.length() == size)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void setButton(Button button) {
+ this.button = button;
+ if (this.state == STATE_STANDBY) {
+ buttonProgressStart();
+ }
+ }
+
+ public InputStream getThumbnail() {
+ InputStream thumbnail = null;
+ URL url;
+ try {
+ String query = URLEncoder.encode(href, StandardCharsets.UTF_8.toString());
+ String serverUrl = root + "/thumbnail.php?file=" + query;
+ url = new URL(protocol, host, port, serverUrl);
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("GET");
+ conn.setConnectTimeout(2000);
+
+ conn.connect();
+
+ thumbnail = conn.getInputStream();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return thumbnail;
+ }
+
+ public void downloadFile() throws IOException {
+
+ URL url = null;
+ HttpURLConnection conn = null;
+ int maxBufferSize = 1 * 1024 * 1024;
+ byte[] buffer = new byte[maxBufferSize];
+ int bufferLength;
+ loaded = 0;
+
+ String[] parts = href.split("/");
+ String path = "";
+ for(int i=0; i< parts.length - 1; i++) {
+ path = path + parts[i] + "/";
+ }
+ String query = URLEncoder.encode(parts[parts.length - 1], StandardCharsets.UTF_8.toString());
+ url = new URL(protocol, host, port, path + query.replace("+", "%20"));
+ conn = (HttpURLConnection) url.openConnection();
+ conn.setDoOutput(true);
+ conn.setRequestMethod("GET");
+ conn.setConnectTimeout(2000);
+
+ Log.d("URL", url.toString());
+
+ conn.connect();
+
+ int responseCode = conn.getResponseCode();
+
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+
+ OutputStream fileOutput = activity.getContentResolver().openOutputStream(uri);
+ InputStream in = conn.getInputStream();
+
+ while ((bufferLength = in.read(buffer)) > 0) {
+ fileOutput.write(buffer, 0, bufferLength);
+ loaded+= bufferLength;
+ percent = ((loaded * 100) / size);
+ progressUpdateDelay();
+ buttonProgressUpdate();
+ }
+ fileOutput.close();
+
+ conn.disconnect();
+
+ message = "File " + name + " successful download";
+ state = Transfer.STATE_SUCCESS;
+ progressEnd();
+ buttonProgressEnd();
+
+ }
+ else {
+ String s = conn.getResponseMessage();
+ throw new HttpErrorException("error code: " + responseCode + " " + s);
+ }
+
+ conn.disconnect();
+ }
+
+ public String deleteFile() throws IOException {
+
+ URL url = null;
+ HttpURLConnection conn = null;
+
+ String message;
+
+ String query = URLEncoder.encode(name, StandardCharsets.UTF_8.toString());
+ String serverUrl = root + "/delete.php?file=" + query;
+ url = new URL(protocol, host, port, serverUrl);
+ conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("GET");
+ conn.setConnectTimeout(2000);
+
+ conn.connect();
+
+ int responseCode = conn.getResponseCode();
+
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+
+ message = "File " + name + " successful deleted";
+ }
+ else {
+ String s = conn.getResponseMessage();
+ throw new HttpErrorException("error code: " + responseCode + " " + s);
+ }
+
+ conn.disconnect();
+
+ return message;
+ }
+
+ public void buttonProgressStart() {
+ activity.runOnUiThread(() -> {
+ final Drawable image = Transfer.activity.getDrawable(R.drawable.ic_spinner_rotate);
+
+ if(button != null) {
+ int h = image.getIntrinsicHeight();
+ int w = image.getIntrinsicWidth();
+ image.setBounds(0, 0, w, h);
+ button.setCompoundDrawables(button.getCompoundDrawables()[0], null, image, null);
+ ObjectAnimator anim = ObjectAnimator.ofInt(image, "level", 0, 10000);
+ anim.setDuration(1000);
+ anim.setRepeatCount(Animation.INFINITE);
+ anim.setInterpolator(new LinearInterpolator());
+ anim.start();
+ }
+ });
+ }
+
+ private void buttonProgressUpdate(){
+ activity.runOnUiThread(() -> {
+ if (app_started && button != null)
+ button.setText(String.format("Download in progress %d%%", percent));
+ });
+ }
+
+ public void buttonProgressEnd() {
+ activity.runOnUiThread(() -> {
+ if (button != null) {
+ final LinearLayout layout = (LinearLayout) button.getParent();
+ layout.findViewById(R.id.file_view).setVisibility(LinearLayout.VISIBLE);
+ layout.findViewById(R.id.file_share).setVisibility(LinearLayout.VISIBLE);
+ button.setVisibility(LinearLayout.GONE);
+ button.setEnabled(true);
+
+ button.setText(activity.getString(R.string.file_download));
+ button.setCompoundDrawables(button.getCompoundDrawables()[0], null, null, null);
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/localtransfer/MainActivity.java b/app/src/main/java/com/localtransfer/MainActivity.java
index 097fee6..15497f5 100644
--- a/app/src/main/java/com/localtransfer/MainActivity.java
+++ b/app/src/main/java/com/localtransfer/MainActivity.java
@@ -2,31 +2,33 @@ package com.localtransfer;
import android.Manifest;
import android.app.Activity;
+import android.app.Notification;
+import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
-
-import com.google.android.material.floatingactionbutton.FloatingActionButton;
-import com.google.android.material.snackbar.Snackbar;
-import com.google.android.material.tabs.TabLayout;
-
-import androidx.appcompat.widget.Toolbar;
-import androidx.core.app.ActivityCompat;
-import androidx.core.content.ContextCompat;
-import androidx.preference.PreferenceManager;
-import androidx.viewpager.widget.ViewPager;
-import androidx.appcompat.app.AppCompatActivity;
-
import android.os.Environment;
import android.util.Log;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+import androidx.core.app.ActivityCompat;
+import androidx.core.app.NotificationManagerCompat;
+import androidx.core.content.ContextCompat;
+import androidx.preference.PreferenceManager;
+import androidx.viewpager.widget.ViewPager;
+
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import com.google.android.material.tabs.TabLayout;
+
import java.io.File;
import java.util.ArrayList;
@@ -63,6 +65,15 @@ public class MainActivity extends AppCompatActivity {
checkAndRequestPermissions();
}
+
+ Transfer.notifBuilder = new Notification.Builder(this);
+ Transfer.notifiManager = NotificationManagerCompat.from(this);
+ Transfer.inflater = (LayoutInflater) this.getSystemService(this.LAYOUT_INFLATER_SERVICE);
+ Transfer.resolver = this.getContentResolver();
+
+ Intent notificationIntent = new Intent(this, MainActivity.class);
+ Transfer.pendingIntent = PendingIntent.getActivity(this,0, notificationIntent, 0);
+
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if(prefs.getString("host", null) == null)
@@ -70,7 +81,8 @@ public class MainActivity extends AppCompatActivity {
.putString("host", getString(R.string.server_host_def))
.putString("port", getString(R.string.server_port_def))
.putString("root", getString(R.string.server_root_def))
- .putString("local_storage", getString(R.string.local_storage_def))
+ .putString("shared_storage", getString(R.string.shared_storage_def))
+ .putBoolean("use_shared_storage", false)
.apply();
Transfer.parameter(this);
@@ -80,16 +92,14 @@ public class MainActivity extends AppCompatActivity {
String action = intent.getAction();
String type = intent.getType();
- Transfer tr = new Transfer();
-
if (Intent.ACTION_SEND.equals(action) && type != null) {
viewPager.setCurrentItem(2);
if ("text/plain".equals(type)) {
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
- tr.handleSendText(sharedText);
+ UploadFile.handleSendText(sharedText);
} else {
Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
- tr.handleSendFile(uri);
+ UploadFile.handleSendFile(uri);
}
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
viewPager.setCurrentItem(2);
@@ -97,7 +107,7 @@ public class MainActivity extends AppCompatActivity {
int nbItem = fileUris.size();
Toast.makeText(this, "You select " + nbItem + " files", Toast.LENGTH_SHORT).show();
if (fileUris != null)
- for(Uri uri : fileUris) tr.handleSendFile(uri);
+ for(Uri uri : fileUris) UploadFile.handleSendFile(uri);
}
}
@@ -112,11 +122,10 @@ public class MainActivity extends AppCompatActivity {
ViewPager viewPager = this.findViewById(R.id.view_pager);
viewPager.setCurrentItem(2);
- Transfer tr = new Transfer();
if (type != null) {
String sharedText = data.getStringExtra(Intent.EXTRA_TEXT);
- tr.handleSendText(sharedText);
+ UploadFile.handleSendText(sharedText);
}
else {
ArrayList fileUris = new ArrayList<>();
@@ -132,7 +141,7 @@ public class MainActivity extends AppCompatActivity {
fileUris.add(uri);
}
for (Uri uri : fileUris) {
- tr.handleSendFile(uri);
+ UploadFile.handleSendFile(uri);
}
}
}
@@ -142,14 +151,14 @@ public class MainActivity extends AppCompatActivity {
public void onResume(){
super.onResume();
- Progress.app_started = true;
+ Transfer.app_started = true;
}
@Override
public void onPause(){
super.onPause();
- Progress.app_started = false;
+ Transfer.app_started = false;
}
@Override
@@ -187,7 +196,7 @@ public class MainActivity extends AppCompatActivity {
startActivity(settings);
break;
case R.id.action_folder:
- String save_location = Environment.getExternalStorageDirectory() + "/" + Transfer.local_storage;
+ String save_location = Environment.getExternalStorageDirectory() + "/" + Transfer.shared_storage;
Uri selectedUri = Uri.parse(save_location.toString());
boolean intentSuccess = false;
try {
diff --git a/app/src/main/java/com/localtransfer/Progress.java b/app/src/main/java/com/localtransfer/Progress.java
deleted file mode 100644
index 983ffe5..0000000
--- a/app/src/main/java/com/localtransfer/Progress.java
+++ /dev/null
@@ -1,188 +0,0 @@
-package com.localtransfer;
-
-import android.app.PendingIntent;
-import android.content.Intent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import androidx.core.app.NotificationCompat;
-import androidx.core.app.NotificationManagerCompat;
-
-import java.util.ArrayList;
-import java.util.ConcurrentModificationException;
-import java.util.List;
-import java.util.Timer;
-import java.util.TimerTask;
-
-public class Progress {
-
- public static final int UPLOAD = 1000;
- public static final int DOWNLOAD = 1001;
-
-
- private static NotificationCompat.Builder bl = new NotificationCompat.Builder(Transfer.activity, null);
- private static NotificationManagerCompat notifiManager = NotificationManagerCompat.from(Transfer.activity);
- private static final LayoutInflater inflater = (LayoutInflater) Transfer.activity.getSystemService(Transfer.activity.LAYOUT_INFLATER_SERVICE);
-
- private static List