lionel 168e01e09a Foreground Service Integration
- Add Foreground Service
- Reviewed Progress Method
- Reviewed Transfer Object Integration
- Fix Some Error
2021-03-17 23:09:23 +01:00

522 lines
16 KiB
Java

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.provider.OpenableColumns;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
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.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.CharacterIterator;
import java.text.SimpleDateFormat;
import java.text.StringCharacterIterator;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import static java.lang.Integer.valueOf;
public class Transfer {
public static String host;
public static Integer port;
public static String root;
public static String protocol;
public static String local_storage;
public static Activity activity;
public static final int STATE_STANDBY = 100;
public static final int STATE_RUNNING = 101;
public static final int STATE_SUCCESS = 102;
public static final int STATE_FAILED = 103;
public static final int TYPE_DOWNLOAD = 200;
public static final int TYPE_UPLOAD = 201;
public static final int NOTIF_SERVICE = 1000;
public static final int NOTIF_GROUP = 1001;
public static boolean runningTransfer = false;
private static List<Transfer> instances = new ArrayList<>();
public static List getInstances() {
return instances;
}
public int state;
public String error;
public int type;
public Integer id;
public int drawable;
public String info;
public String message;
public String fileName;
public long fileSize;
public String fileSizeHuman;
public long loaded;
public String loadedHuman = "0";
public long percent;
public Transfer(int type) {
id = View.generateViewId();
switch (type) {
case TYPE_DOWNLOAD:
drawable = R.drawable.ic_download_24;
info = "Download complete";
break;
case TYPE_UPLOAD:
drawable = R.drawable.ic_upload_24;
info = "Upload complete";
break;
default:
throw new IllegalStateException("Unexpected value: " + type);
}
state = STATE_STANDBY;
this.type = type;
}
public void AddTransfer() {
instances.add(this);
if(!runningTransfer) {
Intent serviceIntent = new Intent(activity, TransferService.class);
ContextCompat.startForegroundService(activity, serviceIntent);
runningTransfer = true;
new Thread(() -> StartTransfer(this)).start();
}
}
private static void StartTransfer(Transfer tr) {
try {
switch (tr.type) {
case Transfer.TYPE_DOWNLOAD:
tr.downloadFile();
break;
case Transfer.TYPE_UPLOAD:
tr.uploadFile();
break;
default:
throw new IllegalStateException("Unexpected value: " + tr.type);
}
} catch (IOException e) {
final String ExceptionName = e.getClass().getSimpleName();
final String ExceptionMess = e.getMessage();
tr.state = Transfer.STATE_FAILED;
tr.error = ExceptionName + ": " + ExceptionMess;
Progress.PostProgress(tr);
if(ExceptionName != null && ExceptionMess != null) {
Transfer.error(ExceptionMess);
}
}
try {
for (Object obj : Transfer.getInstances()) {
Transfer transfer = (Transfer) obj;
if (transfer.state == Transfer.STATE_STANDBY)
StartTransfer(transfer);
}
} catch (ConcurrentModificationException e) {
e.printStackTrace();
try {
Thread.sleep(10);
} catch (InterruptedException InterrupEx) {
InterrupEx.printStackTrace();
}
for (Object obj : Transfer.getInstances()) {
Transfer transfer = (Transfer) obj;
if (transfer.state == Transfer.STATE_STANDBY)
StartTransfer(transfer);
}
}
Intent serviceIntent = new Intent(Transfer.activity, TransferService.class);
Transfer.activity.stopService(serviceIntent);
Transfer.runningTransfer = false;
}
public static void parameter(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
host = prefs.getString("host", null);
port = valueOf(prefs.getString("port", null));
root = prefs.getString("root", null);
local_storage = prefs.getString("local_storage", null);
if(prefs.getBoolean("protocol", false))
protocol = "https";
else
protocol = "http";
}
public Uri uri;
public static void handleSendFile(Uri uri) {
if (uri != null) {
Transfer tr = new Transfer(Transfer.TYPE_UPLOAD);
tr.uri = uri;
Cursor cursor = activity.getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
tr.fileName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
tr.fileSize = cursor.getLong(cursor.getColumnIndex(OpenableColumns.SIZE));
tr.fileSizeHuman = Transfer.humanReadableByteCountBin(tr.fileSize);
tr.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);
}
}
public String uploadFile() throws IOException {
URL url = null;
HttpURLConnection conn = null;
DataOutputStream request = null;
String boundary = "*****";
int maxBufferSize = 1 * 1024 * 1024;
byte[] buffer = new byte[maxBufferSize];
int bufferLength;
loaded = 0;
String fileNameUTF8 = new String(fileName.getBytes(), StandardCharsets.ISO_8859_1);
String type = activity.getContentResolver().getType(uri);
url = new URL(protocol, host, port, root + "/upload.php");
url = checkRedirection(url);
Progress.PreProgress(this);
if(url != null) {
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);
while ((bufferLength = in.read(buffer)) > 0) {
request.write(buffer, 0, bufferLength);
loaded+= (long) bufferLength;
loadedHuman = Transfer.humanReadableByteCountBin(loaded);
percent = ((loaded * 100) / fileSize);
Progress.ProgressUpdateDelay(this);
}
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;
Progress.PostProgress(this);
}
else {
String s = conn.getResponseMessage();
throw new HttpErrorException("HTTP Error code " + responseCode + " " + s);
}
request.flush();
request.close();
conn.disconnect();
}
return message;
}
public File file;
public String href;
public Button button;
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;
Progress.PreProgress(this);
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) {
FileOutputStream fileOutput = new FileOutputStream(file);
InputStream in = conn.getInputStream();
while ((bufferLength = in.read(buffer)) > 0) {
fileOutput.write(buffer, 0, bufferLength);
loaded+= (long) bufferLength;
loadedHuman = Transfer.humanReadableByteCountBin(loaded);
percent = ((loaded * 100) / fileSize);
Progress.ProgressUpdateDelay(this);
}
fileOutput.close();
conn.disconnect();
message = "File " + fileName + " successful download";
state = Transfer.STATE_SUCCESS;
Progress.PostProgress(this);
}
else {
String s = conn.getResponseMessage();
throw new HttpErrorException("HTTP Error code " + responseCode + " " + s);
}
conn.disconnect();
}
public static boolean setButton(String name, Button button) {
for (Object obj: instances) {
Transfer tr = (Transfer) obj;
if (name.equals(tr.fileName) && tr.state == STATE_RUNNING) {
tr.button = button;
return true;
}
}
return false;
}
public static String getFileList() throws IOException {
URL url = null;
HttpURLConnection conn = null;
String fileList = "";
int buf;
url = new URL(protocol, host, port, root + "/list.php");
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(2000);
conn.connect();
int responseCode = conn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStreamReader isw = new InputStreamReader(conn.getInputStream());
while ((buf = isw.read()) > 0) {
fileList = fileList + (char) buf;
}
}
else {
String s = conn.getResponseMessage();
throw new HttpErrorException("HTTP Error code " + responseCode + " " + s);
}
conn.disconnect();
return fileList;
}
public static String deleteFile(String file) throws IOException {
URL url = null;
HttpURLConnection conn = null;
String message;
String query = URLEncoder.encode(file, 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 " + file + " successful deleted";
}
else {
String s = conn.getResponseMessage();
throw new HttpErrorException("HTTP Error code " + responseCode + " " + s);
}
conn.disconnect();
return message;
}
private static URL checkRedirection(URL url) throws IOException {
String location = null;
HttpURLConnection conn = null;
int responseCode;
int nbRedirect = 0;
do {
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setInstanceFollowRedirects(false);
conn.setConnectTimeout(2000);
conn.connect();
responseCode = conn.getResponseCode();
Log.d("Réponse Code", String.valueOf(responseCode));
if(responseCode != HttpURLConnection.HTTP_MOVED_PERM && responseCode != HttpURLConnection.HTTP_MOVED_TEMP) {
break;
}
location = conn.getHeaderField("Location");
Log.d("Location", location);
url = new URL(location);
conn.disconnect();
nbRedirect++;
if(nbRedirect > 10) {
throw new ProtocolException("Too many follow-up requests: " + nbRedirect);
}
} while (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP);
return url;
}
public static void error(final String message) {
System.out.println(message);
if (activity != null) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Snackbar.make(activity.findViewById(R.id.view_pager), message, Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
}
public static String humanReadableByteCountBin(long bytes) {
long absB = bytes == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(bytes);
if (absB < 1024) {
return bytes + " B";
}
long value = absB;
CharacterIterator ci = new StringCharacterIterator("KMGTPE");
for (int i = 40; i >= 0 && absB > 0xfffccccccccccccL >> i; i -= 10) {
value >>= 10;
ci.next();
}
value *= Long.signum(bytes);
return String.format("%.1f %ciB", value / 1024.0, ci.current());
}
}