Merge branch 'foregroundService'
This commit is contained in:
		
							
								
								
									
										5
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							@ -3,8 +3,11 @@
 | 
			
		||||
  <component name="DesignSurface">
 | 
			
		||||
    <option name="filePathToZoomLevelMap">
 | 
			
		||||
      <map>
 | 
			
		||||
        <entry key="app/src/main/res/layout/file_info.xml" value="0.24479166666666666" />
 | 
			
		||||
        <entry key="app/src/main/res/layout/layout.xml" value="0.35989583333333336" />
 | 
			
		||||
        <entry key="app/src/main/res/layout/settings_activity.xml" value="0.215625" />
 | 
			
		||||
        <entry key="app/src/main/res/xml/network_security_config.xml" value="0.35989583333333336" />
 | 
			
		||||
        <entry key="app/src/main/res/xml/root_preferences.xml" value="0.35833333333333334" />
 | 
			
		||||
      </map>
 | 
			
		||||
    </option>
 | 
			
		||||
  </component>
 | 
			
		||||
@ -52,7 +55,7 @@
 | 
			
		||||
      </value>
 | 
			
		||||
    </option>
 | 
			
		||||
  </component>
 | 
			
		||||
  <component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="1.8" project-jdk-type="JavaSDK">
 | 
			
		||||
  <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
 | 
			
		||||
    <output url="file://$PROJECT_DIR$/build/classes" />
 | 
			
		||||
  </component>
 | 
			
		||||
  <component name="ProjectType">
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@ android {
 | 
			
		||||
        minSdkVersion 24
 | 
			
		||||
        targetSdkVersion 30
 | 
			
		||||
        versionCode 1
 | 
			
		||||
        versionName "1.0"
 | 
			
		||||
        versionName "2.0"
 | 
			
		||||
 | 
			
		||||
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -3,20 +3,25 @@
 | 
			
		||||
    package="com.localtransfer">
 | 
			
		||||
 | 
			
		||||
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 | 
			
		||||
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
 | 
			
		||||
    <uses-permission
 | 
			
		||||
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
 | 
			
		||||
        android:maxSdkVersion="28" />
 | 
			
		||||
    <uses-permission android:name="android.permission.INTERNET" />
 | 
			
		||||
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
 | 
			
		||||
 | 
			
		||||
    <application
 | 
			
		||||
        android:icon="@mipmap/ic_launcher"
 | 
			
		||||
        android:label="@string/app_name"
 | 
			
		||||
        android:networkSecurityConfig="@xml/network_security_config"
 | 
			
		||||
        android:requestLegacyExternalStorage="true"
 | 
			
		||||
        android:roundIcon="@mipmap/ic_launcher_round"
 | 
			
		||||
        android:supportsRtl="true"
 | 
			
		||||
        android:theme="@style/AppTheme"
 | 
			
		||||
        android:networkSecurityConfig="@xml/network_security_config"
 | 
			
		||||
        android:requestLegacyExternalStorage="true">
 | 
			
		||||
        <!--android:usesCleartextTraffic="true"-->
 | 
			
		||||
 | 
			
		||||
        android:theme="@style/AppTheme">
 | 
			
		||||
        <service
 | 
			
		||||
            android:name=".TransferService"
 | 
			
		||||
            android:enabled="true"
 | 
			
		||||
            android:exported="true"></service>
 | 
			
		||||
        <!-- android:usesCleartextTraffic="true" -->
 | 
			
		||||
        <provider
 | 
			
		||||
            android:name="androidx.core.content.FileProvider"
 | 
			
		||||
            android:authorities="${applicationId}"
 | 
			
		||||
@ -29,31 +34,30 @@
 | 
			
		||||
 | 
			
		||||
        <activity
 | 
			
		||||
            android:name=".SettingsActivity"
 | 
			
		||||
            android:label="@string/title_activity_settings">
 | 
			
		||||
        </activity>
 | 
			
		||||
 | 
			
		||||
            android:label="@string/title_activity_settings"></activity>
 | 
			
		||||
        <activity
 | 
			
		||||
            android:name=".MainActivity"
 | 
			
		||||
            android:label="@string/app_name"
 | 
			
		||||
            android:theme="@style/AppTheme.NoActionBar">
 | 
			
		||||
 | 
			
		||||
            <intent-filter>
 | 
			
		||||
                <action android:name="android.intent.action.MAIN" />
 | 
			
		||||
 | 
			
		||||
                <category android:name="android.intent.category.LAUNCHER" />
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
 | 
			
		||||
            <intent-filter>
 | 
			
		||||
                <action android:name="android.intent.action.SEND" />
 | 
			
		||||
 | 
			
		||||
                <category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
 | 
			
		||||
                <data android:mimeType="*/*" />
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
 | 
			
		||||
            <intent-filter>
 | 
			
		||||
                <action android:name="android.intent.action.SEND_MULTIPLE" />
 | 
			
		||||
 | 
			
		||||
                <category android:name="android.intent.category.DEFAULT" />
 | 
			
		||||
 | 
			
		||||
                <data android:mimeType="*/*" />
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
 | 
			
		||||
        </activity>
 | 
			
		||||
    </application>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										289
									
								
								app/src/main/java/com/localtransfer/DownloadFile.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								app/src/main/java/com/localtransfer/DownloadFile.java
									
									
									
									
									
										Normal file
									
								
							@ -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);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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<Uri> 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 {
 | 
			
		||||
 | 
			
		||||
@ -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<Progress> instances = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
    private Integer id;
 | 
			
		||||
    private String name;
 | 
			
		||||
    private long size;
 | 
			
		||||
 | 
			
		||||
    public long loaded;
 | 
			
		||||
    public long percent;
 | 
			
		||||
 | 
			
		||||
    public static View root;
 | 
			
		||||
    public static boolean fragment_on = false;
 | 
			
		||||
    public static boolean app_started = false;
 | 
			
		||||
 | 
			
		||||
    private Timer timer = new Timer();
 | 
			
		||||
    private int drawable;
 | 
			
		||||
    private String info;
 | 
			
		||||
 | 
			
		||||
    public Button button;
 | 
			
		||||
    private boolean run = false;
 | 
			
		||||
 | 
			
		||||
    public Progress(String name, long size, int type) {
 | 
			
		||||
 | 
			
		||||
        instances.add(this);
 | 
			
		||||
 | 
			
		||||
        run = true;
 | 
			
		||||
 | 
			
		||||
        this.name = name;
 | 
			
		||||
        this.size = size;
 | 
			
		||||
 | 
			
		||||
        id = View.generateViewId();
 | 
			
		||||
 | 
			
		||||
        switch (type) {
 | 
			
		||||
            case Progress.DOWNLOAD:
 | 
			
		||||
                drawable = R.drawable.ic_download_24;
 | 
			
		||||
                info = "Download complete";
 | 
			
		||||
                break;
 | 
			
		||||
            case Progress.UPLOAD:
 | 
			
		||||
                drawable = R.drawable.ic_upload_24;
 | 
			
		||||
                info = "Upload complete";
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                throw new IllegalStateException("Unexpected value: " + type);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        timer.schedule(new TimerTask() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void run() {
 | 
			
		||||
                showProgress();
 | 
			
		||||
            }
 | 
			
		||||
        }, 0, 1000);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static List getInstances() {
 | 
			
		||||
        return instances;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void stopProgress() {
 | 
			
		||||
        timer.cancel();
 | 
			
		||||
        showProgress();
 | 
			
		||||
 | 
			
		||||
        run = false;
 | 
			
		||||
 | 
			
		||||
        if(! app_started) {
 | 
			
		||||
            bl.setSmallIcon(R.drawable.ic_upload_and_download_from_the_cloud)
 | 
			
		||||
                    .setContentTitle(name)
 | 
			
		||||
                    .setContentText(info)
 | 
			
		||||
                    .setProgress(0, 0, false)
 | 
			
		||||
                    .setAutoCancel(true)
 | 
			
		||||
                    .setOngoing(false);
 | 
			
		||||
            notifiManager.notify(id, bl.build());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void delete() {
 | 
			
		||||
        instances.remove(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Progress getProgress(int id) {
 | 
			
		||||
 | 
			
		||||
        for (Object obj: instances) {
 | 
			
		||||
            Progress p = (Progress) obj;
 | 
			
		||||
            if (p.id == id) return p;
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean setButton(String name, Button button) {
 | 
			
		||||
 | 
			
		||||
        for (Object obj: instances) {
 | 
			
		||||
            Progress p = (Progress) obj;
 | 
			
		||||
            if (name.equals(p.name) && p.run) {
 | 
			
		||||
                p.button = button;
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public void showProgress(){
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
 | 
			
		||||
            String HumanLoaded = Transfer.humanReadableByteCountBin(loaded);
 | 
			
		||||
            String HumanSize = Transfer.humanReadableByteCountBin(size);
 | 
			
		||||
 | 
			
		||||
            if(app_started) {
 | 
			
		||||
                notifiManager.cancel(id);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
 | 
			
		||||
                Intent intent = new Intent(Transfer.activity, MainActivity.class);
 | 
			
		||||
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
 | 
			
		||||
                PendingIntent pendingIntent = PendingIntent.getActivity(Transfer.activity, 0, intent, 0);
 | 
			
		||||
 | 
			
		||||
                bl.setSmallIcon(R.drawable.ic_upload_and_download_from_the_cloud)
 | 
			
		||||
                        .setContentTitle(name)
 | 
			
		||||
                        .setContentText(String.format("%d%% %s/%s", percent, HumanLoaded, HumanSize))
 | 
			
		||||
                        .setProgress(100, (int) percent, false)
 | 
			
		||||
                        .setContentIntent(pendingIntent)
 | 
			
		||||
                        .setAutoCancel(true)
 | 
			
		||||
                        .setOngoing(true);
 | 
			
		||||
                notifiManager.notify(id, bl.build());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(app_started && fragment_on) {
 | 
			
		||||
                LinearLayout groot = root.findViewById(R.id.groot);
 | 
			
		||||
 | 
			
		||||
                final View progress;
 | 
			
		||||
 | 
			
		||||
                if (groot.findViewById(id) != null) {
 | 
			
		||||
                    progress = groot.findViewById(id);
 | 
			
		||||
                } else {
 | 
			
		||||
                    progress = inflater.inflate(R.layout.progress, null);
 | 
			
		||||
                    progress.setId(id);
 | 
			
		||||
                    Transfer.activity.runOnUiThread(() -> {
 | 
			
		||||
                        groot.addView(progress, 0);
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Transfer.activity.runOnUiThread(() -> {
 | 
			
		||||
                    ((ProgressBar) progress.findViewById(R.id.progressBar)).setProgress((int) percent);
 | 
			
		||||
                    ((ImageView) progress.findViewById(R.id.transferType)).setImageResource(drawable);
 | 
			
		||||
                    ((TextView) progress.findViewById(R.id.progressText)).setText(percent + " %");
 | 
			
		||||
                    ((TextView) progress.findViewById(R.id.fileName)).setText(name);
 | 
			
		||||
                    ((TextView) progress.findViewById(R.id.fileSize)).setText(String.format("%s/%s", HumanLoaded, HumanSize));
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } catch (ConcurrentModificationException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -1,217 +0,0 @@
 | 
			
		||||
package com.localtransfer;
 | 
			
		||||
 | 
			
		||||
import android.content.ContentUris;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.database.Cursor;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.provider.MediaStore;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
import android.widget.Button;
 | 
			
		||||
import android.widget.LinearLayout;
 | 
			
		||||
 | 
			
		||||
import com.google.android.material.snackbar.Snackbar;
 | 
			
		||||
 | 
			
		||||
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.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public class ServerFile extends Transfer {
 | 
			
		||||
 | 
			
		||||
    private Integer id;
 | 
			
		||||
 | 
			
		||||
    public String name;
 | 
			
		||||
 | 
			
		||||
    public String href;
 | 
			
		||||
 | 
			
		||||
    public String mime;
 | 
			
		||||
 | 
			
		||||
    public String type;
 | 
			
		||||
 | 
			
		||||
    public long size;
 | 
			
		||||
 | 
			
		||||
    public String save_location;
 | 
			
		||||
 | 
			
		||||
    public Uri uri;
 | 
			
		||||
 | 
			
		||||
    public Button button;
 | 
			
		||||
 | 
			
		||||
    public Progress progress;
 | 
			
		||||
 | 
			
		||||
    private static List<ServerFile> instances = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
    public ServerFile(Integer id) {
 | 
			
		||||
        this.id = id;
 | 
			
		||||
        instances.add(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static List getInstances() {
 | 
			
		||||
        return instances;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static ServerFile getFileById(int id) {
 | 
			
		||||
        for (Object obj: instances) {
 | 
			
		||||
            ServerFile p = (ServerFile) obj;
 | 
			
		||||
            if (p.id == id) return p;
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Integer getId() {
 | 
			
		||||
        return id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean exist(Context context) {
 | 
			
		||||
        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 {
 | 
			
		||||
            File file = new File(save_location, name);
 | 
			
		||||
            new File(save_location).mkdirs();
 | 
			
		||||
            uri = Uri.fromFile(file);
 | 
			
		||||
            if (file.exists() && file.length() == size)
 | 
			
		||||
                return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
        long 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+= (long) bufferLength;
 | 
			
		||||
                progress.loaded = loaded;
 | 
			
		||||
                progress.percent = ((loaded * 100) / size);
 | 
			
		||||
                if(Progress.app_started && progress.button != null)
 | 
			
		||||
                    activity.runOnUiThread(() -> progress.button.setText(String.format("Download in progress %d%%", progress.percent)));
 | 
			
		||||
            }
 | 
			
		||||
            fileOutput.close();
 | 
			
		||||
 | 
			
		||||
            conn.disconnect();
 | 
			
		||||
 | 
			
		||||
            progress.stopProgress();
 | 
			
		||||
 | 
			
		||||
            if(progress.button != null) {
 | 
			
		||||
                activity.runOnUiThread(() -> {
 | 
			
		||||
                    final LinearLayout layout = (LinearLayout) progress.button.getParent();
 | 
			
		||||
                    layout.findViewById(R.id.file_view).setVisibility(LinearLayout.VISIBLE);
 | 
			
		||||
                    layout.findViewById(R.id.file_share).setVisibility(LinearLayout.VISIBLE);
 | 
			
		||||
                    progress.button.setVisibility(LinearLayout.GONE);
 | 
			
		||||
                    progress.button.setEnabled(true);
 | 
			
		||||
 | 
			
		||||
                    progress.button.setText(activity.getString(R.string.file_download));
 | 
			
		||||
                    progress.button.setCompoundDrawables(progress.button.getCompoundDrawables()[0], null, null, null);
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            activity.runOnUiThread(() -> {
 | 
			
		||||
                String message = "File " + name + " successful download";
 | 
			
		||||
                System.out.println(message);
 | 
			
		||||
                Snackbar.make(activity.findViewById(R.id.view_pager), message, Snackbar.LENGTH_LONG)
 | 
			
		||||
                        .setAction("Action", null).show();
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,14 +1,10 @@
 | 
			
		||||
package com.localtransfer;
 | 
			
		||||
 | 
			
		||||
import android.app.Activity;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.content.SharedPreferences;
 | 
			
		||||
import android.database.Cursor;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.os.Environment;
 | 
			
		||||
import android.provider.MediaStore;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
import android.view.MenuItem;
 | 
			
		||||
 | 
			
		||||
@ -17,6 +13,7 @@ import androidx.appcompat.app.AppCompatActivity;
 | 
			
		||||
import androidx.preference.Preference;
 | 
			
		||||
import androidx.preference.PreferenceFragmentCompat;
 | 
			
		||||
import androidx.preference.PreferenceManager;
 | 
			
		||||
import androidx.preference.SwitchPreference;
 | 
			
		||||
 | 
			
		||||
import lib.folderpicker.FolderPicker;
 | 
			
		||||
 | 
			
		||||
@ -46,8 +43,24 @@ public class SettingsActivity extends AppCompatActivity {
 | 
			
		||||
            setPreferencesFromResource(R.xml.root_preferences, rootKey);
 | 
			
		||||
 | 
			
		||||
            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
 | 
			
		||||
            directory = findPreference("local_storage");
 | 
			
		||||
            directory.setSummary(prefs.getString("local_storage", null));
 | 
			
		||||
 | 
			
		||||
            directory = findPreference("shared_storage");
 | 
			
		||||
            directory.setSummary(prefs.getString("shared_storage", null));
 | 
			
		||||
 | 
			
		||||
            SwitchPreference shared;
 | 
			
		||||
            shared = findPreference("use_shared_storage");
 | 
			
		||||
            if(shared.isChecked())
 | 
			
		||||
                directory.setVisible(true);
 | 
			
		||||
            else
 | 
			
		||||
                directory.setVisible(false);
 | 
			
		||||
 | 
			
		||||
            shared.setOnPreferenceClickListener(preference -> {
 | 
			
		||||
                if(shared.isChecked())
 | 
			
		||||
                    directory.setVisible(true);
 | 
			
		||||
                else
 | 
			
		||||
                    directory.setVisible(false);
 | 
			
		||||
                return false;
 | 
			
		||||
            });
 | 
			
		||||
            directory.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
 | 
			
		||||
                @Override
 | 
			
		||||
                public boolean onPreferenceClick(Preference preference) {
 | 
			
		||||
@ -69,7 +82,7 @@ public class SettingsActivity extends AppCompatActivity {
 | 
			
		||||
                            String save_location = currentPath.replace(Environment.getExternalStorageDirectory() + "/", "");
 | 
			
		||||
                            Log.d("Path", save_location);
 | 
			
		||||
                            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
 | 
			
		||||
                            prefs.edit().putString("local_storage", save_location).apply();
 | 
			
		||||
                            prefs.edit().putString("shared_storage", save_location).apply();
 | 
			
		||||
                            directory.setSummary(save_location);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
@ -1,64 +1,133 @@
 | 
			
		||||
package com.localtransfer;
 | 
			
		||||
 | 
			
		||||
import android.animation.ObjectAnimator;
 | 
			
		||||
import static java.lang.Integer.valueOf;
 | 
			
		||||
 | 
			
		||||
import android.app.Activity;
 | 
			
		||||
import android.app.Notification;
 | 
			
		||||
import android.app.PendingIntent;
 | 
			
		||||
import android.content.ContentResolver;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.SharedPreferences;
 | 
			
		||||
import android.database.Cursor;
 | 
			
		||||
import android.graphics.drawable.Drawable;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.provider.OpenableColumns;
 | 
			
		||||
import android.graphics.Color;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
import android.view.Gravity;
 | 
			
		||||
import android.view.animation.Animation;
 | 
			
		||||
import android.view.animation.LinearInterpolator;
 | 
			
		||||
import android.widget.Button;
 | 
			
		||||
import android.view.LayoutInflater;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.widget.ImageView;
 | 
			
		||||
import android.widget.LinearLayout;
 | 
			
		||||
import android.widget.ProgressBar;
 | 
			
		||||
import android.widget.TextView;
 | 
			
		||||
import android.widget.Toast;
 | 
			
		||||
 | 
			
		||||
import androidx.core.content.FileProvider;
 | 
			
		||||
import androidx.core.app.NotificationManagerCompat;
 | 
			
		||||
import androidx.preference.PreferenceManager;
 | 
			
		||||
 | 
			
		||||
import com.google.android.material.snackbar.Snackbar;
 | 
			
		||||
 | 
			
		||||
import java.io.DataOutputStream;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.InputStreamReader;
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
import java.io.OutputStreamWriter;
 | 
			
		||||
import java.net.HttpURLConnection;
 | 
			
		||||
import java.net.ProtocolException;
 | 
			
		||||
import java.net.URL;
 | 
			
		||||
import java.net.URLEncoder;
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
import java.sql.Timestamp;
 | 
			
		||||
import java.text.CharacterIterator;
 | 
			
		||||
import java.text.SimpleDateFormat;
 | 
			
		||||
import java.text.StringCharacterIterator;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import java.util.Timer;
 | 
			
		||||
import java.util.TimerTask;
 | 
			
		||||
 | 
			
		||||
import static java.lang.Integer.valueOf;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Comparator;
 | 
			
		||||
import java.util.ConcurrentModificationException;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public class Transfer {
 | 
			
		||||
 | 
			
		||||
    protected static Notification.Builder notifBuilder;
 | 
			
		||||
    protected static NotificationManagerCompat notifiManager;
 | 
			
		||||
    protected static LayoutInflater inflater;
 | 
			
		||||
    protected static ContentResolver resolver;
 | 
			
		||||
 | 
			
		||||
    protected static PendingIntent pendingIntent;
 | 
			
		||||
 | 
			
		||||
    public static View fragment_progress;
 | 
			
		||||
    public static boolean fragment_on = false;
 | 
			
		||||
    public static boolean app_started = false;
 | 
			
		||||
 | 
			
		||||
    protected static long savedTimeMillis;
 | 
			
		||||
 | 
			
		||||
    public static String host;
 | 
			
		||||
    public static Integer port;
 | 
			
		||||
    public static String root;
 | 
			
		||||
    public static String protocol;
 | 
			
		||||
    public static String local_storage;
 | 
			
		||||
    public static String shared_storage;
 | 
			
		||||
    public static boolean use_shared_storage;
 | 
			
		||||
 | 
			
		||||
    public static Activity activity;
 | 
			
		||||
 | 
			
		||||
    public int state;
 | 
			
		||||
 | 
			
		||||
    public int drawable;
 | 
			
		||||
    public String info;
 | 
			
		||||
    public String message;
 | 
			
		||||
 | 
			
		||||
    public String sizeSI;
 | 
			
		||||
 | 
			
		||||
    public long loaded;
 | 
			
		||||
    public String loadedSI = "0";
 | 
			
		||||
    public long percent;
 | 
			
		||||
 | 
			
		||||
    public static final int NOTIF_SERVICE = 1000;
 | 
			
		||||
 | 
			
		||||
    public static final int STATE_NOT_REQUESTED = 100;
 | 
			
		||||
    public static final int STATE_STANDBY = 110;
 | 
			
		||||
    public static final int STATE_RUNNING = 120;
 | 
			
		||||
    public static final int STATE_SUCCESS = 130;
 | 
			
		||||
    public static final int STATE_FAILED = 140;
 | 
			
		||||
 | 
			
		||||
    public static Thread thread = new Thread();
 | 
			
		||||
 | 
			
		||||
    Integer id;
 | 
			
		||||
 | 
			
		||||
    public String name;
 | 
			
		||||
 | 
			
		||||
    public long size;
 | 
			
		||||
 | 
			
		||||
    Timestamp addedTime;
 | 
			
		||||
    Timestamp startedTime;
 | 
			
		||||
 | 
			
		||||
    static List<Transfer> instances = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
    public static List<Transfer> getInstances() {
 | 
			
		||||
        List<Transfer> in = new ArrayList<>();
 | 
			
		||||
        for (Transfer file: instances) {
 | 
			
		||||
            //if(Arrays.asList(STATE_STANDBY, STATE_RUNNING, STATE_SUCCESS, STATE_FAILED).contains(file.state)) {
 | 
			
		||||
            if(file.state == STATE_STANDBY ||
 | 
			
		||||
                    file.state == STATE_RUNNING ||
 | 
			
		||||
                    file.state == STATE_SUCCESS ||
 | 
			
		||||
                    file.state == STATE_FAILED) {
 | 
			
		||||
                in.add(file);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        //in.sort(Comparator.comparing(Transfer::getAddedTime).reversed());
 | 
			
		||||
        in.sort(Comparator.comparing(e -> e.addedTime));
 | 
			
		||||
        return in;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Transfer getFileById(int id) {
 | 
			
		||||
        for (Object obj: instances) {
 | 
			
		||||
            Transfer p = (Transfer) obj;
 | 
			
		||||
            if (p.id == id) return p;
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Integer getId() {
 | 
			
		||||
        return id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void parameter(Context context) {
 | 
			
		||||
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
 | 
			
		||||
 | 
			
		||||
        host = prefs.getString("host", null);
 | 
			
		||||
        root = prefs.getString("root", null);
 | 
			
		||||
        local_storage = prefs.getString("local_storage", null);
 | 
			
		||||
        shared_storage = prefs.getString("shared_storage", null);
 | 
			
		||||
        use_shared_storage = prefs.getBoolean("use_shared_storage", false);
 | 
			
		||||
        if(prefs.getBoolean("protocol", false))
 | 
			
		||||
            protocol = "https";
 | 
			
		||||
        else
 | 
			
		||||
@ -74,7 +143,127 @@ public class Transfer {
 | 
			
		||||
            port = valueOf(portValue);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static URL checkRedirection(URL url) throws IOException {
 | 
			
		||||
    public void AddTransfer() {
 | 
			
		||||
 | 
			
		||||
        state = STATE_STANDBY;
 | 
			
		||||
 | 
			
		||||
        addedTime = new Timestamp(System.currentTimeMillis());
 | 
			
		||||
 | 
			
		||||
        Thread.State state = thread.getState();
 | 
			
		||||
 | 
			
		||||
        if(state == Thread.State.NEW || state == Thread.State.TERMINATED) {
 | 
			
		||||
            thread = new Thread(startTransfers);
 | 
			
		||||
            thread.start();
 | 
			
		||||
 | 
			
		||||
            /*Intent serviceIntent = new Intent(activity, TransferService.class);
 | 
			
		||||
            ContextCompat.startForegroundService(activity, serviceIntent);*/
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void startTransfer() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Runnable startTransfers = () -> {
 | 
			
		||||
        try {
 | 
			
		||||
            for (Transfer transfer : getInstances()) {
 | 
			
		||||
                if (transfer.state == Transfer.STATE_STANDBY) {
 | 
			
		||||
                    transfer.startTransfer();
 | 
			
		||||
                    thread.run(); // restart thread for another potential standby transfer
 | 
			
		||||
                    break; // ignore remainder instance
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } catch (ConcurrentModificationException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    /*Intent serviceIntent = new Intent(Transfer.activity, TransferService.class);
 | 
			
		||||
    Transfer.activity.stopService(serviceIntent);*/
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    public void progressUpdateDelay() {
 | 
			
		||||
        // Run only every second to reduce CPU usage
 | 
			
		||||
        if (System.currentTimeMillis() > (savedTimeMillis + 1000)) {
 | 
			
		||||
            savedTimeMillis = System.currentTimeMillis();
 | 
			
		||||
            progressUpdate();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void progressUpdate(){
 | 
			
		||||
 | 
			
		||||
        loadedSI = Transfer.humanReadableByteCountBin(loaded);
 | 
			
		||||
 | 
			
		||||
        activity.runOnUiThread(() -> {
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
 | 
			
		||||
                notifBuilder.setSmallIcon(R.drawable.ic_upload_and_download_from_the_cloud)
 | 
			
		||||
                        .setContentTitle(name)
 | 
			
		||||
                        .setContentText(String.format("%d%% %s/%s", percent, loadedSI, sizeSI))
 | 
			
		||||
                        .setProgress(100, (int) percent, false)
 | 
			
		||||
                        .setContentIntent(pendingIntent);
 | 
			
		||||
                notifiManager.notify(Transfer.NOTIF_SERVICE, notifBuilder.build());
 | 
			
		||||
 | 
			
		||||
                if (app_started && fragment_on)
 | 
			
		||||
                    showProgressFragment();
 | 
			
		||||
 | 
			
		||||
            } catch (ConcurrentModificationException e) {
 | 
			
		||||
                e.printStackTrace();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void progressEnd() {
 | 
			
		||||
        progressUpdate();
 | 
			
		||||
        activity.runOnUiThread(() -> {
 | 
			
		||||
 | 
			
		||||
            notifiManager.cancel(Transfer.NOTIF_SERVICE);
 | 
			
		||||
 | 
			
		||||
            if (!app_started) {
 | 
			
		||||
                notifBuilder.setSmallIcon(R.drawable.ic_upload_and_download_from_the_cloud)
 | 
			
		||||
                        .setContentTitle(name)
 | 
			
		||||
                        .setContentText(info)
 | 
			
		||||
                        .setProgress(0, 0, false)
 | 
			
		||||
                        .setContentIntent(pendingIntent);
 | 
			
		||||
                notifiManager.notify(id, notifBuilder.build());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            System.out.println(message);
 | 
			
		||||
            /*Snackbar.make(Transfer.activity.findViewById(R.id.view_pager), tr.message, Snackbar.LENGTH_LONG)
 | 
			
		||||
                    .setAction("Action", null).show();*/
 | 
			
		||||
            Toast.makeText(activity, message, Toast.LENGTH_SHORT).show();
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void showProgressFragment(){
 | 
			
		||||
 | 
			
		||||
        LinearLayout groot = fragment_progress.findViewById(R.id.groot);
 | 
			
		||||
 | 
			
		||||
        View progress = groot.findViewById(id);
 | 
			
		||||
 | 
			
		||||
        if (progress == null) {
 | 
			
		||||
            progress = inflater.inflate(R.layout.progress, null);
 | 
			
		||||
            progress.setId(id);
 | 
			
		||||
            final View final_progress = progress;
 | 
			
		||||
            activity.runOnUiThread(() -> {
 | 
			
		||||
                groot.addView(final_progress, 0);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ((ProgressBar) progress.findViewById(R.id.progressBar)).setProgress((int) percent);
 | 
			
		||||
        ((ImageView) progress.findViewById(R.id.transferType)).setImageResource(drawable);
 | 
			
		||||
        ((TextView) progress.findViewById(R.id.progressText)).setText(percent + " %");
 | 
			
		||||
        ((TextView) progress.findViewById(R.id.fileName)).setText(name);
 | 
			
		||||
        ((TextView) progress.findViewById(R.id.fileSize)).setText(String.format("%s/%s", loadedSI, sizeSI));
 | 
			
		||||
 | 
			
		||||
        if (state == Transfer.STATE_SUCCESS)
 | 
			
		||||
            ((TextView) progress.findViewById(R.id.fileName)).setTextColor(Color.GREEN);
 | 
			
		||||
        else if (state == Transfer.STATE_FAILED)
 | 
			
		||||
            ((TextView) progress.findViewById(R.id.fileName)).setTextColor(Color.RED);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static URL checkRedirection(URL url) throws IOException {
 | 
			
		||||
        String location = null;
 | 
			
		||||
        HttpURLConnection conn = null;
 | 
			
		||||
        int responseCode;
 | 
			
		||||
@ -115,149 +304,6 @@ public class Transfer {
 | 
			
		||||
        return url;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void handleSendFile(Uri uri) {
 | 
			
		||||
        if (uri != null) {
 | 
			
		||||
            new Thread(() -> {
 | 
			
		||||
                try {
 | 
			
		||||
                    Transfer.uploadFile(uri);
 | 
			
		||||
                } catch (IOException e) {
 | 
			
		||||
                    final String ExceptionName = e.getClass().getSimpleName();
 | 
			
		||||
                    final String ExceptionMess = e.getMessage();
 | 
			
		||||
 | 
			
		||||
                    if(ExceptionName != null && ExceptionMess != null) {
 | 
			
		||||
                        Transfer.error(ExceptionName + ": " + ExceptionMess, null, null);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
            }).start();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void handleSendText(String sharedText) {
 | 
			
		||||
        if (sharedText != null) {
 | 
			
		||||
            SimpleDateFormat sdfDate = new SimpleDateFormat("text_yyyyMMdd_HHmmss");
 | 
			
		||||
            Date now = new Date();
 | 
			
		||||
            String strDate = sdfDate.format(now);
 | 
			
		||||
            new Thread(() -> {
 | 
			
		||||
                try {
 | 
			
		||||
                    File outputFile = new File(activity.getCacheDir(), strDate + ".txt");
 | 
			
		||||
                    FileOutputStream fileOut = new FileOutputStream(outputFile);
 | 
			
		||||
                    OutputStreamWriter OutWriter = new OutputStreamWriter(fileOut);
 | 
			
		||||
                    OutWriter.append(sharedText);
 | 
			
		||||
                    OutWriter.close();
 | 
			
		||||
 | 
			
		||||
                    fileOut.flush();
 | 
			
		||||
                    fileOut.close();
 | 
			
		||||
 | 
			
		||||
                    Uri uri = FileProvider.getUriForFile(activity, activity.getPackageName(), outputFile);
 | 
			
		||||
 | 
			
		||||
                    Transfer.uploadFile(uri);
 | 
			
		||||
                } catch (IOException e) {
 | 
			
		||||
                    e.printStackTrace();
 | 
			
		||||
                }
 | 
			
		||||
            }).start();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String uploadFile(Uri uri) throws IOException {
 | 
			
		||||
        String message = null;
 | 
			
		||||
        URL url = null;
 | 
			
		||||
        HttpURLConnection conn = null;
 | 
			
		||||
        DataOutputStream request = null;
 | 
			
		||||
        String boundary = "*****";
 | 
			
		||||
        final int maxBufferSize = 1 * 1024 * 1024;
 | 
			
		||||
        byte[] buffer = new byte[maxBufferSize];
 | 
			
		||||
        int bufferLength;
 | 
			
		||||
        long loaded = 0;
 | 
			
		||||
 | 
			
		||||
        Cursor cursor = activity.getContentResolver().query(uri, null, null, null, null);
 | 
			
		||||
        cursor.moveToFirst();
 | 
			
		||||
 | 
			
		||||
        String type = activity.getContentResolver().getType(uri);
 | 
			
		||||
 | 
			
		||||
        String fileName = null;
 | 
			
		||||
        int col_name = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
 | 
			
		||||
        if (col_name != -1)
 | 
			
		||||
            fileName = cursor.getString(col_name);
 | 
			
		||||
        if(fileName == null)
 | 
			
		||||
            fileName = type.split("/")[0] + "_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + "." + type.split("/")[1];
 | 
			
		||||
        String fileNameUTF8 = new String(fileName.getBytes(), StandardCharsets.ISO_8859_1);
 | 
			
		||||
 | 
			
		||||
        long fileSize = -1;
 | 
			
		||||
        int col_size = cursor.getColumnIndex(OpenableColumns.SIZE);
 | 
			
		||||
        if (col_size != -1)
 | 
			
		||||
            fileSize = cursor.getLong(col_size);
 | 
			
		||||
 | 
			
		||||
        url = new URL(protocol, host, port, root + "/upload.php");
 | 
			
		||||
 | 
			
		||||
        url = checkRedirection(url);
 | 
			
		||||
 | 
			
		||||
        Log.d("URL", url.toString());
 | 
			
		||||
 | 
			
		||||
        conn = (HttpURLConnection) url.openConnection();
 | 
			
		||||
        conn.setDoInput(true); // Allow Inputs
 | 
			
		||||
        conn.setDoOutput(true); // Allow Outputs
 | 
			
		||||
        conn.setUseCaches(false); // Don't use a Cached Copy
 | 
			
		||||
        conn.setChunkedStreamingMode(maxBufferSize);
 | 
			
		||||
        conn.setRequestMethod("POST");
 | 
			
		||||
        conn.setRequestProperty("Connection", "keep-alive");
 | 
			
		||||
        conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
 | 
			
		||||
 | 
			
		||||
        conn.connect();
 | 
			
		||||
 | 
			
		||||
        request = new DataOutputStream(conn.getOutputStream());
 | 
			
		||||
 | 
			
		||||
        request.writeBytes("--" + boundary + "\r\n");
 | 
			
		||||
        request.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"" + fileNameUTF8 + "\"\r\n");
 | 
			
		||||
        request.writeBytes("Content-Type: " + type + "\r\n\r\n");
 | 
			
		||||
 | 
			
		||||
        InputStream in = activity.getContentResolver().openInputStream(uri);
 | 
			
		||||
 | 
			
		||||
        if (fileSize < 1)
 | 
			
		||||
            fileSize = in.available();
 | 
			
		||||
 | 
			
		||||
        Progress p = new Progress(fileName, fileSize, Progress.UPLOAD);
 | 
			
		||||
 | 
			
		||||
        while ((bufferLength = in.read(buffer)) > 0) {
 | 
			
		||||
            request.write(buffer, 0, bufferLength);
 | 
			
		||||
            loaded+= (long) bufferLength;
 | 
			
		||||
            p.loaded = loaded;
 | 
			
		||||
            p.percent = ((loaded * 100) / fileSize);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        request.writeBytes("\r\n");
 | 
			
		||||
        request.writeBytes("--" + boundary + "--\r\n");
 | 
			
		||||
 | 
			
		||||
        in.close();
 | 
			
		||||
 | 
			
		||||
        int responseCode = conn.getResponseCode();
 | 
			
		||||
 | 
			
		||||
        if (responseCode == HttpURLConnection.HTTP_OK) {
 | 
			
		||||
            message = "File " + fileName + " successful upload";
 | 
			
		||||
            p.stopProgress();
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            String s = conn.getResponseMessage();
 | 
			
		||||
            throw new HttpErrorException("error code: " + responseCode + " " + s);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        request.flush();
 | 
			
		||||
 | 
			
		||||
        request.close();
 | 
			
		||||
 | 
			
		||||
        conn.disconnect();
 | 
			
		||||
 | 
			
		||||
        System.out.println(message);
 | 
			
		||||
        if (activity != null) {
 | 
			
		||||
            String finalMessage = message;
 | 
			
		||||
            activity.runOnUiThread(() ->
 | 
			
		||||
                    Snackbar.make(activity.findViewById(R.id.view_pager), finalMessage, Snackbar.LENGTH_LONG)
 | 
			
		||||
                            .setAction("Action", null).show());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return message;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String getFileList() throws IOException {
 | 
			
		||||
        URL url = null;
 | 
			
		||||
        HttpURLConnection conn = null;
 | 
			
		||||
@ -292,33 +338,13 @@ public class Transfer {
 | 
			
		||||
 | 
			
		||||
    private static int timeout;
 | 
			
		||||
 | 
			
		||||
    public static void error(final String message, final TextView title, final LinearLayout layout) {
 | 
			
		||||
    public static void errorSnackbar(final String message) {
 | 
			
		||||
 | 
			
		||||
        System.out.println(message);
 | 
			
		||||
 | 
			
		||||
        if (timeout == 0) {
 | 
			
		||||
        if (activity != null) {
 | 
			
		||||
                activity.runOnUiThread(() -> {
 | 
			
		||||
                    if(layout != null)
 | 
			
		||||
                        layout.removeAllViews();
 | 
			
		||||
                    if(title != null) {
 | 
			
		||||
                        title.setTextSize(18);
 | 
			
		||||
                        title.setGravity(Gravity.CENTER);
 | 
			
		||||
                        title.setHeight(1000);
 | 
			
		||||
                        layout.addView(title);
 | 
			
		||||
                        title.setText(message);
 | 
			
		||||
                    }
 | 
			
		||||
                    Snackbar.make(activity.findViewById(R.id.view_pager), message, Snackbar.LENGTH_LONG)
 | 
			
		||||
                            .setAction("Action", null).show();
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            timeout = 1;
 | 
			
		||||
            new Timer().schedule(new TimerTask() {
 | 
			
		||||
                @Override
 | 
			
		||||
                public void run() {
 | 
			
		||||
                    timeout = 0;
 | 
			
		||||
                }
 | 
			
		||||
            }, 3000);
 | 
			
		||||
            activity.runOnUiThread(() -> Snackbar.make(activity.findViewById(R.id.view_pager), message, Snackbar.LENGTH_LONG)
 | 
			
		||||
                    .setAction("Action", null).show());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										42
									
								
								app/src/main/java/com/localtransfer/TransferService.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								app/src/main/java/com/localtransfer/TransferService.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
			
		||||
package com.localtransfer;
 | 
			
		||||
 | 
			
		||||
import android.app.Notification;
 | 
			
		||||
import android.app.PendingIntent;
 | 
			
		||||
import android.app.Service;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.os.IBinder;
 | 
			
		||||
 | 
			
		||||
import androidx.core.app.NotificationCompat;
 | 
			
		||||
 | 
			
		||||
public class TransferService extends Service {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onCreate() {
 | 
			
		||||
        super.onCreate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int onStartCommand(Intent intent, int flags, int startId) {
 | 
			
		||||
 | 
			
		||||
        Intent notificationIntent = new Intent(this, MainActivity.class);
 | 
			
		||||
        PendingIntent pendingIntent = PendingIntent.getActivity(this,
 | 
			
		||||
                0, notificationIntent, 0);
 | 
			
		||||
 | 
			
		||||
        Notification notification = new NotificationCompat.Builder(this, "CHANNEL_ID")
 | 
			
		||||
                .setContentIntent(pendingIntent)
 | 
			
		||||
                .build();
 | 
			
		||||
 | 
			
		||||
        startForeground(Transfer.NOTIF_SERVICE, notification);
 | 
			
		||||
 | 
			
		||||
        //do heavy work on a background thread
 | 
			
		||||
        //stopSelf();
 | 
			
		||||
 | 
			
		||||
        return START_NOT_STICKY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public IBinder onBind(Intent intent) {
 | 
			
		||||
        // TODO: Return the communication channel to the service.
 | 
			
		||||
        throw new UnsupportedOperationException("Not yet implemented");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										196
									
								
								app/src/main/java/com/localtransfer/UploadFile.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								app/src/main/java/com/localtransfer/UploadFile.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,196 @@
 | 
			
		||||
package com.localtransfer;
 | 
			
		||||
 | 
			
		||||
import android.database.Cursor;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.provider.OpenableColumns;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
 | 
			
		||||
import androidx.core.content.FileProvider;
 | 
			
		||||
 | 
			
		||||
import com.google.android.material.snackbar.Snackbar;
 | 
			
		||||
 | 
			
		||||
import java.io.DataOutputStream;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.OutputStreamWriter;
 | 
			
		||||
import java.net.HttpURLConnection;
 | 
			
		||||
import java.net.URL;
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
import java.sql.Timestamp;
 | 
			
		||||
import java.text.SimpleDateFormat;
 | 
			
		||||
import java.util.ConcurrentModificationException;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
 | 
			
		||||
public class UploadFile extends Transfer {
 | 
			
		||||
 | 
			
		||||
    public Uri uri;
 | 
			
		||||
 | 
			
		||||
    public UploadFile() {
 | 
			
		||||
        this.id = View.generateViewId();
 | 
			
		||||
        instances.add(this);
 | 
			
		||||
        info = "Upload complete";
 | 
			
		||||
        state = STATE_NOT_REQUESTED;
 | 
			
		||||
        drawable = R.drawable.ic_upload_24;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void handleSendFile(Uri uri) {
 | 
			
		||||
        if (uri != null) {
 | 
			
		||||
            UploadFile file = new UploadFile();
 | 
			
		||||
            file.uri = uri;
 | 
			
		||||
 | 
			
		||||
            Cursor cursor = activity.getContentResolver().query(uri, null, null, null, null);
 | 
			
		||||
            cursor.moveToFirst();
 | 
			
		||||
 | 
			
		||||
            file.name = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
 | 
			
		||||
            file.size = cursor.getLong(cursor.getColumnIndex(OpenableColumns.SIZE));
 | 
			
		||||
            file.sizeSI = Transfer.humanReadableByteCountBin(file.size);
 | 
			
		||||
 | 
			
		||||
            file.AddTransfer();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void handleSendText(String sharedText) {
 | 
			
		||||
        if (sharedText != null) {
 | 
			
		||||
            SimpleDateFormat sdfDate = new SimpleDateFormat("yyyyMMdd_HHmmss");
 | 
			
		||||
            Date now = new Date();
 | 
			
		||||
            String strDate = sdfDate.format(now);
 | 
			
		||||
            Uri uri = null;
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                File outputFile = new File(activity.getCacheDir(), strDate + ".txt");
 | 
			
		||||
                FileOutputStream fileOut = new FileOutputStream(outputFile);
 | 
			
		||||
                OutputStreamWriter OutWriter = new OutputStreamWriter(fileOut);
 | 
			
		||||
                OutWriter.append(sharedText);
 | 
			
		||||
                OutWriter.close();
 | 
			
		||||
 | 
			
		||||
                fileOut.flush();
 | 
			
		||||
                fileOut.close();
 | 
			
		||||
 | 
			
		||||
                uri = FileProvider.getUriForFile(activity, activity.getPackageName(), outputFile);
 | 
			
		||||
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
                e.printStackTrace();
 | 
			
		||||
            }
 | 
			
		||||
            handleSendFile(uri);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void startTransfer() {
 | 
			
		||||
        super.startTransfer();
 | 
			
		||||
 | 
			
		||||
        startedTime = new Timestamp(System.currentTimeMillis());
 | 
			
		||||
 | 
			
		||||
        state = STATE_RUNNING;
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            uploadFile();
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            final String ExceptionName = e.getClass().getSimpleName();
 | 
			
		||||
            final String ExceptionMess = e.getMessage();
 | 
			
		||||
 | 
			
		||||
            state = Transfer.STATE_FAILED;
 | 
			
		||||
            progressEnd();
 | 
			
		||||
 | 
			
		||||
            if(ExceptionName != null && ExceptionMess != null) {
 | 
			
		||||
                errorSnackbar(ExceptionMess);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String uploadFile() throws IOException {
 | 
			
		||||
        String message = null;
 | 
			
		||||
        URL url = null;
 | 
			
		||||
        HttpURLConnection conn = null;
 | 
			
		||||
        DataOutputStream request = null;
 | 
			
		||||
        String boundary = "*****";
 | 
			
		||||
        final int maxBufferSize = 1 * 1024 * 1024;
 | 
			
		||||
        byte[] buffer = new byte[maxBufferSize];
 | 
			
		||||
        int bufferLength;
 | 
			
		||||
        loaded = 0;
 | 
			
		||||
 | 
			
		||||
        Cursor cursor = activity.getContentResolver().query(uri, null, null, null, null);
 | 
			
		||||
        cursor.moveToFirst();
 | 
			
		||||
 | 
			
		||||
        String type = activity.getContentResolver().getType(uri);
 | 
			
		||||
 | 
			
		||||
        String fileName = null;
 | 
			
		||||
        int col_name = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
 | 
			
		||||
        if (col_name != -1)
 | 
			
		||||
            fileName = cursor.getString(col_name);
 | 
			
		||||
        if(fileName == null)
 | 
			
		||||
            fileName = type.split("/")[0] + "_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + "." + type.split("/")[1];
 | 
			
		||||
        String fileNameUTF8 = new String(fileName.getBytes(), StandardCharsets.ISO_8859_1);
 | 
			
		||||
 | 
			
		||||
        url = new URL(protocol, host, port, root + "/upload.php");
 | 
			
		||||
 | 
			
		||||
        url = checkRedirection(url);
 | 
			
		||||
 | 
			
		||||
        Log.d("URL", url.toString());
 | 
			
		||||
 | 
			
		||||
        conn = (HttpURLConnection) url.openConnection();
 | 
			
		||||
        conn.setDoInput(true); // Allow Inputs
 | 
			
		||||
        conn.setDoOutput(true); // Allow Outputs
 | 
			
		||||
        conn.setUseCaches(false); // Don't use a Cached Copy
 | 
			
		||||
        conn.setChunkedStreamingMode(maxBufferSize);
 | 
			
		||||
        conn.setRequestMethod("POST");
 | 
			
		||||
        conn.setRequestProperty("Connection", "keep-alive");
 | 
			
		||||
        conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
 | 
			
		||||
 | 
			
		||||
        conn.connect();
 | 
			
		||||
 | 
			
		||||
        request = new DataOutputStream(conn.getOutputStream());
 | 
			
		||||
 | 
			
		||||
        request.writeBytes("--" + boundary + "\r\n");
 | 
			
		||||
        request.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"" + fileNameUTF8 + "\"\r\n");
 | 
			
		||||
        request.writeBytes("Content-Type: " + type + "\r\n\r\n");
 | 
			
		||||
 | 
			
		||||
        InputStream in = activity.getContentResolver().openInputStream(uri);
 | 
			
		||||
 | 
			
		||||
        size = in.available();
 | 
			
		||||
 | 
			
		||||
        while ((bufferLength = in.read(buffer)) > 0) {
 | 
			
		||||
            request.write(buffer, 0, bufferLength);
 | 
			
		||||
            loaded+= bufferLength;
 | 
			
		||||
            percent = ((loaded * 100) / size);
 | 
			
		||||
            progressUpdateDelay();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        request.writeBytes("\r\n");
 | 
			
		||||
        request.writeBytes("--" + boundary + "--\r\n");
 | 
			
		||||
 | 
			
		||||
        in.close();
 | 
			
		||||
 | 
			
		||||
        int responseCode = conn.getResponseCode();
 | 
			
		||||
 | 
			
		||||
        if (responseCode == HttpURLConnection.HTTP_OK) {
 | 
			
		||||
            message = "File " + fileName + " successful upload";
 | 
			
		||||
            state = Transfer.STATE_SUCCESS;
 | 
			
		||||
            progressEnd();
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            String s = conn.getResponseMessage();
 | 
			
		||||
            throw new HttpErrorException("error code: " + responseCode + " " + s);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        request.flush();
 | 
			
		||||
 | 
			
		||||
        request.close();
 | 
			
		||||
 | 
			
		||||
        conn.disconnect();
 | 
			
		||||
 | 
			
		||||
        System.out.println(message);
 | 
			
		||||
        if (activity != null) {
 | 
			
		||||
            String finalMessage = message;
 | 
			
		||||
            activity.runOnUiThread(() ->
 | 
			
		||||
                    Snackbar.make(activity.findViewById(R.id.view_pager), finalMessage, Snackbar.LENGTH_LONG)
 | 
			
		||||
                            .setAction("Action", null).show());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return message;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -2,14 +2,12 @@ package com.localtransfer.fragment;
 | 
			
		||||
 | 
			
		||||
import android.animation.ObjectAnimator;
 | 
			
		||||
import android.content.ActivityNotFoundException;
 | 
			
		||||
import android.content.ContentValues;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.graphics.Bitmap;
 | 
			
		||||
import android.graphics.BitmapFactory;
 | 
			
		||||
import android.graphics.drawable.Drawable;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.os.Environment;
 | 
			
		||||
import android.provider.MediaStore;
 | 
			
		||||
import android.view.ContextMenu;
 | 
			
		||||
import android.view.Gravity;
 | 
			
		||||
import android.view.LayoutInflater;
 | 
			
		||||
@ -22,15 +20,15 @@ import android.widget.Button;
 | 
			
		||||
import android.widget.ImageView;
 | 
			
		||||
import android.widget.LinearLayout;
 | 
			
		||||
import android.widget.TextView;
 | 
			
		||||
import android.widget.Toast;
 | 
			
		||||
 | 
			
		||||
import androidx.fragment.app.Fragment;
 | 
			
		||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
 | 
			
		||||
 | 
			
		||||
import com.google.android.material.snackbar.Snackbar;
 | 
			
		||||
import com.localtransfer.Progress;
 | 
			
		||||
import com.localtransfer.R;
 | 
			
		||||
import com.localtransfer.DownloadFile;
 | 
			
		||||
import com.localtransfer.Transfer;
 | 
			
		||||
import com.localtransfer.ServerFile;
 | 
			
		||||
 | 
			
		||||
import org.json.JSONArray;
 | 
			
		||||
import org.json.JSONException;
 | 
			
		||||
@ -111,7 +109,7 @@ public class DownloadFragment extends Fragment {
 | 
			
		||||
    public boolean onContextItemSelected(MenuItem item) {
 | 
			
		||||
        if (item.getTitle() == "Delete") {
 | 
			
		||||
            LinearLayout fileDesc = (LinearLayout) root.findViewById(item.getItemId());
 | 
			
		||||
            ServerFile file = ServerFile.getFileById((Integer) fileDesc.getTag(R.id.ID_DOWNLOAD));
 | 
			
		||||
            DownloadFile file = (DownloadFile) DownloadFile.getFileById((Integer) fileDesc.getTag(R.id.ID_DOWNLOAD));
 | 
			
		||||
            new Thread(() -> {
 | 
			
		||||
                try {
 | 
			
		||||
                    String message = file.deleteFile();
 | 
			
		||||
@ -125,7 +123,7 @@ public class DownloadFragment extends Fragment {
 | 
			
		||||
                    String ExceptionMess = e.getMessage();
 | 
			
		||||
 | 
			
		||||
                    if(ExceptionName != null && ExceptionMess != null) {
 | 
			
		||||
                        Transfer.error(ExceptionName + ": " + ExceptionMess, null, null);
 | 
			
		||||
                        Transfer.errorSnackbar(ExceptionMess);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
@ -164,7 +162,7 @@ public class DownloadFragment extends Fragment {
 | 
			
		||||
                        JSONArray array = new JSONArray(data);
 | 
			
		||||
                        for (int i = 0; i < array.length(); i++) {
 | 
			
		||||
                            Integer id = View.generateViewId();
 | 
			
		||||
                            ServerFile trFile = new ServerFile(id);
 | 
			
		||||
                            DownloadFile trFile = new DownloadFile(id);
 | 
			
		||||
 | 
			
		||||
                            JSONObject row = array.getJSONObject(i);
 | 
			
		||||
                            trFile.name = row.getString("name");
 | 
			
		||||
@ -185,14 +183,14 @@ public class DownloadFragment extends Fragment {
 | 
			
		||||
                final String ExceptionMess = e.getMessage();
 | 
			
		||||
 | 
			
		||||
                if(ExceptionName != null && ExceptionMess != null) {
 | 
			
		||||
                    Transfer.error(ExceptionName + ": " + ExceptionMess, title, main_layout);
 | 
			
		||||
                    Transfer.errorSnackbar(ExceptionMess);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }).start();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void setThumbnail(ServerFile file, ImageView image) {
 | 
			
		||||
    private void setThumbnail(DownloadFile file, ImageView image) {
 | 
			
		||||
        new Thread(() -> {
 | 
			
		||||
            InputStream thumbnail = file.getThumbnail();
 | 
			
		||||
            Bitmap bitmap = BitmapFactory.decodeStream(thumbnail);
 | 
			
		||||
@ -202,7 +200,7 @@ public class DownloadFragment extends Fragment {
 | 
			
		||||
        }).start();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void showFileList(ServerFile trFile) {
 | 
			
		||||
    private void showFileList(DownloadFile trFile) {
 | 
			
		||||
 | 
			
		||||
        final LinearLayout main_layout = root.findViewById(R.id.main_layout);
 | 
			
		||||
 | 
			
		||||
@ -224,12 +222,8 @@ public class DownloadFragment extends Fragment {
 | 
			
		||||
        fileDesc.setTag(R.id.ID_DOWNLOAD, trFile.getId());
 | 
			
		||||
        file_buttons.setTag(R.id.ID_FILE_BUTTONS, "FOR VISIBILITY");
 | 
			
		||||
 | 
			
		||||
        trFile.button = file_buttons.findViewById(R.id.file_download);
 | 
			
		||||
 | 
			
		||||
        if (trFile.mime.equals("text/plain"))
 | 
			
		||||
            trFile.save_location = getContext().getCacheDir().toString();
 | 
			
		||||
        else
 | 
			
		||||
            trFile.save_location = Environment.getExternalStorageDirectory() + "/" + Transfer.local_storage;
 | 
			
		||||
        trFile.setButton(file_buttons.findViewById(R.id.file_download));
 | 
			
		||||
 | 
			
		||||
        viewName.setText(trFile.name);
 | 
			
		||||
        viewType.setText(trFile.mime);
 | 
			
		||||
@ -272,19 +266,7 @@ public class DownloadFragment extends Fragment {
 | 
			
		||||
                Bshare.setVisibility(LinearLayout.GONE);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (Progress.setButton(trFile.name, Bdownload)) {
 | 
			
		||||
                Bdownload.setEnabled(false);
 | 
			
		||||
                final Drawable spinner = Transfer.activity.getDrawable(R.drawable.ic_spinner_rotate);
 | 
			
		||||
                int h = spinner.getIntrinsicHeight();
 | 
			
		||||
                int w = spinner.getIntrinsicWidth();
 | 
			
		||||
                spinner.setBounds(0, 0, w, h);
 | 
			
		||||
                Bdownload.setCompoundDrawables(Bdownload.getCompoundDrawables()[0], null, spinner, null);
 | 
			
		||||
                ObjectAnimator anim = ObjectAnimator.ofInt(spinner, "level", 0, 10000);
 | 
			
		||||
                anim.setDuration(1000);
 | 
			
		||||
                anim.setRepeatCount(Animation.INFINITE);
 | 
			
		||||
                anim.setInterpolator(new LinearInterpolator());
 | 
			
		||||
                anim.start();
 | 
			
		||||
            }
 | 
			
		||||
            trFile.setButton(Bdownload);
 | 
			
		||||
 | 
			
		||||
            int state = file_buttons.getVisibility();
 | 
			
		||||
            if(state == LinearLayout.GONE) {
 | 
			
		||||
@ -302,54 +284,21 @@ public class DownloadFragment extends Fragment {
 | 
			
		||||
    private View.OnClickListener ListenerDL = v -> {
 | 
			
		||||
        v.setEnabled(false);
 | 
			
		||||
        final LinearLayout layout = (LinearLayout) v.getParent();
 | 
			
		||||
        final Button button = layout.findViewById(R.id.file_download);
 | 
			
		||||
        final Button button = (Button) v;
 | 
			
		||||
        button.setText(String.format("Download pending"));
 | 
			
		||||
 | 
			
		||||
        final Integer id = (Integer) layout.getTag(R.id.ID_DOWNLOAD);
 | 
			
		||||
 | 
			
		||||
        final Drawable image = getActivity().getDrawable(R.drawable.ic_spinner_rotate);
 | 
			
		||||
        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();
 | 
			
		||||
 | 
			
		||||
        ServerFile file = ServerFile.getFileById(id);
 | 
			
		||||
 | 
			
		||||
        file.progress = new Progress(file.name, file.size, Progress.DOWNLOAD);
 | 
			
		||||
        file.progress.button = file.button;
 | 
			
		||||
 | 
			
		||||
        if (file.uri == null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
 | 
			
		||||
            ContentValues values = new ContentValues();
 | 
			
		||||
            values.put(MediaStore.MediaColumns.DISPLAY_NAME, file.name);
 | 
			
		||||
            values.put(MediaStore.MediaColumns.MIME_TYPE, file.mime);
 | 
			
		||||
            values.put(MediaStore.MediaColumns.RELATIVE_PATH, Transfer.local_storage);
 | 
			
		||||
            file.uri = getContext().getContentResolver().insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        new Thread(() -> {
 | 
			
		||||
            try {
 | 
			
		||||
                file.downloadFile();
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
                final String ExceptionName = e.getClass().getSimpleName();
 | 
			
		||||
                final String ExceptionMess = e.getMessage();
 | 
			
		||||
 | 
			
		||||
                if(ExceptionName != null && ExceptionMess != null) {
 | 
			
		||||
                    Transfer.error(ExceptionName + ": " + ExceptionMess, null, null);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }).start();
 | 
			
		||||
        DownloadFile file = (DownloadFile) DownloadFile.getFileById(id);
 | 
			
		||||
        file.sizeSI = Transfer.humanReadableByteCountBin(file.size);
 | 
			
		||||
        file.AddTransfer();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private View.OnClickListener ListenerShare = v -> {
 | 
			
		||||
        LinearLayout layout = (LinearLayout) v.getParent();
 | 
			
		||||
        final Integer id = (Integer) layout.getTag(R.id.ID_DOWNLOAD);
 | 
			
		||||
 | 
			
		||||
        ServerFile dl = ServerFile.getFileById(id);
 | 
			
		||||
        DownloadFile dl = (DownloadFile) DownloadFile.getFileById(id);
 | 
			
		||||
 | 
			
		||||
        if(dl.type.equals("text/plain")) {
 | 
			
		||||
            String text = null;
 | 
			
		||||
@ -377,6 +326,7 @@ public class DownloadFragment extends Fragment {
 | 
			
		||||
                startActivity(Intent.createChooser(intent, getString(R.string.share_title)));
 | 
			
		||||
            } catch (ActivityNotFoundException e) {
 | 
			
		||||
                e.printStackTrace();
 | 
			
		||||
                Toast.makeText(getActivity(), "Can't share " + dl.mime, Toast.LENGTH_SHORT).show();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
@ -388,17 +338,16 @@ public class DownloadFragment extends Fragment {
 | 
			
		||||
                startActivity(Intent.createChooser(intent, getString(R.string.share_title)));
 | 
			
		||||
            } catch (ActivityNotFoundException e) {
 | 
			
		||||
                e.printStackTrace();
 | 
			
		||||
                Toast.makeText(getActivity(), "Can't share " + dl.mime, Toast.LENGTH_SHORT).show();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private View.OnClickListener ListenerView = v -> {
 | 
			
		||||
        LinearLayout layout = (LinearLayout) v.getParent();
 | 
			
		||||
        final Integer id = (Integer) layout.getTag(R.id.ID_DOWNLOAD);
 | 
			
		||||
 | 
			
		||||
        ServerFile dl = ServerFile.getFileById(id);
 | 
			
		||||
        DownloadFile dl = (DownloadFile) DownloadFile.getFileById(id);
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            Intent intent = new Intent(Intent.ACTION_VIEW);
 | 
			
		||||
@ -407,9 +356,8 @@ public class DownloadFragment extends Fragment {
 | 
			
		||||
            startActivity(intent);
 | 
			
		||||
        } catch (ActivityNotFoundException e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
            Toast.makeText(getActivity(), "No " + dl.mime + " viewer", Toast.LENGTH_SHORT).show();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private List<View> getAllChildren(View v) {
 | 
			
		||||
 | 
			
		||||
@ -2,26 +2,16 @@ package com.localtransfer.fragment;
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
 | 
			
		||||
import androidx.core.app.NotificationCompat;
 | 
			
		||||
import androidx.core.app.NotificationManagerCompat;
 | 
			
		||||
import androidx.fragment.app.Fragment;
 | 
			
		||||
 | 
			
		||||
import android.view.LayoutInflater;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.view.ViewGroup;
 | 
			
		||||
import android.widget.ImageView;
 | 
			
		||||
import android.widget.LinearLayout;
 | 
			
		||||
import android.widget.ProgressBar;
 | 
			
		||||
import android.widget.TextView;
 | 
			
		||||
 | 
			
		||||
import com.localtransfer.Progress;
 | 
			
		||||
import com.localtransfer.R;
 | 
			
		||||
import com.localtransfer.Transfer;
 | 
			
		||||
 | 
			
		||||
import java.util.ConcurrentModificationException;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Timer;
 | 
			
		||||
import java.util.TimerTask;
 | 
			
		||||
 | 
			
		||||
public class ProgressFragment extends Fragment {
 | 
			
		||||
 | 
			
		||||
@ -43,21 +33,20 @@ public class ProgressFragment extends Fragment {
 | 
			
		||||
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
 | 
			
		||||
                             Bundle savedInstanceState) {
 | 
			
		||||
        // Inflate the layout for this fragment
 | 
			
		||||
        Progress.root = inflater.inflate(R.layout.fragment_progress, container, false);
 | 
			
		||||
        Transfer.fragment_progress = inflater.inflate(R.layout.fragment_progress, container, false);
 | 
			
		||||
 | 
			
		||||
        return Progress.root;
 | 
			
		||||
        return Transfer.fragment_progress;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onResume(){
 | 
			
		||||
        super.onResume();
 | 
			
		||||
 | 
			
		||||
        Progress.fragment_on = true;
 | 
			
		||||
        Transfer.fragment_on = true;
 | 
			
		||||
 | 
			
		||||
        List instances = Progress.getInstances();
 | 
			
		||||
        for (Object obj: instances) {
 | 
			
		||||
            Progress p = (Progress) obj;
 | 
			
		||||
            p.showProgress();
 | 
			
		||||
        List<Transfer> instances = Transfer.getInstances();
 | 
			
		||||
        for (Transfer file: instances) {
 | 
			
		||||
            file.showProgressFragment();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -65,6 +54,6 @@ public class ProgressFragment extends Fragment {
 | 
			
		||||
    public void onPause(){
 | 
			
		||||
        super.onPause();
 | 
			
		||||
 | 
			
		||||
        Progress.fragment_on = false;
 | 
			
		||||
        Transfer.fragment_on = false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -30,8 +30,9 @@
 | 
			
		||||
    <string name="server_root_def">/transfer</string>
 | 
			
		||||
 | 
			
		||||
    <!-- Local Preferences -->
 | 
			
		||||
    <string name="local_storage">Local Storage</string>
 | 
			
		||||
    <string name="local_storage_def">Download/TransferLocal</string>
 | 
			
		||||
    <string name="use_shared_storage">Use shared storage</string>
 | 
			
		||||
    <string name="shared_storage">Shared Storage</string>
 | 
			
		||||
    <string name="shared_storage_def">Download/TransferLocal</string>
 | 
			
		||||
 | 
			
		||||
    <!-- File buttons -->
 | 
			
		||||
    <string name="file_share">Share</string>
 | 
			
		||||
 | 
			
		||||
@ -31,11 +31,17 @@
 | 
			
		||||
 | 
			
		||||
    <PreferenceCategory app:title="@string/local_header">
 | 
			
		||||
 | 
			
		||||
        <SwitchPreference
 | 
			
		||||
            android:defaultValue="false"
 | 
			
		||||
            android:key="use_shared_storage"
 | 
			
		||||
            android:title="@string/use_shared_storage" />
 | 
			
		||||
 | 
			
		||||
        <Preference
 | 
			
		||||
            app:key="local_storage"
 | 
			
		||||
            app:title="@string/local_storage"
 | 
			
		||||
            app:defaultValue="@string/local_storage_def"
 | 
			
		||||
            app:useSimpleSummaryProvider="true" />
 | 
			
		||||
            app:key="shared_storage"
 | 
			
		||||
            app:title="@string/shared_storage"
 | 
			
		||||
            app:defaultValue="@string/shared_storage_def"
 | 
			
		||||
            app:useSimpleSummaryProvider="true"
 | 
			
		||||
            app:isPreferenceVisible="false"/>
 | 
			
		||||
 | 
			
		||||
    </PreferenceCategory>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user