removed tinyurl logic added support for new short code logic
This commit is contained in:
@@ -14,7 +14,10 @@
|
||||
android:label="SimpleLogUpload"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.AppCompat.DayNight.DarkActionBar"> <!-- Add this line -->
|
||||
android:largeHeap="true"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:theme="@style/Theme.AppCompat.DayNight.DarkActionBar">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true">
|
||||
|
||||
@@ -2,4 +2,28 @@ package com.mattintech.simplelogupload;
|
||||
|
||||
public class Constant {
|
||||
public static final String APP_TAG = "SLU::";
|
||||
|
||||
// Server constants
|
||||
public static final String SERVER_URL = "http://172.16.100.167:7777/upload"; // HTTP protocol explicitly specified
|
||||
|
||||
// File size limits
|
||||
public static final long MAX_FILE_SIZE = 2L * 1024 * 1024 * 1024; // 2GB
|
||||
|
||||
// Upload parameters
|
||||
public static final String PARAM_FILE = "file";
|
||||
public static final String PARAM_MAX_DOWNLOADS = "max_downloads";
|
||||
public static final String PARAM_EXPIRY_HOURS = "expiry_hours";
|
||||
|
||||
// Default values
|
||||
public static final int DEFAULT_MAX_DOWNLOADS = 1;
|
||||
public static final int DEFAULT_EXPIRY_HOURS = 24;
|
||||
public static final int MAX_EXPIRY_HOURS = 24;
|
||||
|
||||
// Broadcast actions
|
||||
public static final String ACTION_UPLOAD_COMPLETE = "com.mattintech.simplelogupload.UPLOAD_COMPLETE";
|
||||
public static final String ACTION_UPLOAD_ERROR = "com.mattintech.simplelogupload.UPLOAD_ERROR";
|
||||
|
||||
// Intent extras
|
||||
public static final String EXTRA_UPLOAD_CODE = "upload_code";
|
||||
public static final String EXTRA_UPLOAD_ERROR = "upload_error";
|
||||
}
|
||||
|
||||
@@ -19,6 +19,12 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import com.mattintech.simplelogupload.model.UploadResult;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
@@ -52,6 +58,7 @@ public class FileUploadForegroundService extends Service {
|
||||
uploadFile(mostRecentFile);
|
||||
} else {
|
||||
Log.e(TAG, "No DUMPSTATE file found.");
|
||||
sendErrorBroadcast("No DUMPSTATE file found");
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
@@ -98,17 +105,34 @@ public class FileUploadForegroundService extends Service {
|
||||
}
|
||||
|
||||
private void uploadFile(File file) {
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
// Validate file size before upload
|
||||
if (file.length() > Constant.MAX_FILE_SIZE) {
|
||||
Log.e(TAG, "File too large: " + file.length() + " bytes (max: " + Constant.MAX_FILE_SIZE + " bytes)");
|
||||
sendErrorBroadcast("File size exceeds the maximum allowed size of 2GB");
|
||||
stopSelf();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create OkHttpClient with timeout configuration for large files
|
||||
OkHttpClient client = new OkHttpClient.Builder()
|
||||
.connectTimeout(60, TimeUnit.SECONDS)
|
||||
.writeTimeout(180, TimeUnit.SECONDS) // 3 minutes timeout for large uploads
|
||||
.readTimeout(60, TimeUnit.SECONDS)
|
||||
.retryOnConnectionFailure(true)
|
||||
.build();
|
||||
|
||||
Log.d(TAG, "Uploading file: " + file.getName() + ", Size: " + file.length());
|
||||
|
||||
RequestBody fileBody = RequestBody.create(file, MediaType.parse("application/zip"));
|
||||
MultipartBody requestBody = new MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM)
|
||||
.addFormDataPart("file", file.getName(), fileBody)
|
||||
.addFormDataPart(Constant.PARAM_FILE, file.getName(), fileBody)
|
||||
.addFormDataPart(Constant.PARAM_MAX_DOWNLOADS, String.valueOf(Constant.DEFAULT_MAX_DOWNLOADS))
|
||||
.addFormDataPart(Constant.PARAM_EXPIRY_HOURS, String.valueOf(Constant.DEFAULT_EXPIRY_HOURS))
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url("http://172.16.30.69:7777/upload") // Replace with your server's URL
|
||||
.url(Constant.SERVER_URL)
|
||||
.post(requestBody)
|
||||
.build();
|
||||
|
||||
@@ -116,20 +140,59 @@ public class FileUploadForegroundService extends Service {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "Upload failed: " + e.getMessage());
|
||||
String errorMsg = "Upload failed: " + e.getMessage();
|
||||
Log.e(TAG, errorMsg);
|
||||
sendErrorBroadcast(errorMsg);
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
String tinyUrl = response.body().string(); // Assuming the server returns tinyURL in response
|
||||
Log.d(TAG, "Upload successful! TinyURL: " + tinyUrl);
|
||||
try {
|
||||
String responseBody = response.body().string();
|
||||
Log.d(TAG, "Server response: " + responseBody);
|
||||
|
||||
// Parse JSON response to get the upload code
|
||||
JSONObject jsonResponse = new JSONObject(responseBody);
|
||||
String uploadCode = jsonResponse.getString("code");
|
||||
|
||||
Log.d(TAG, "Upload successful! Code: " + uploadCode);
|
||||
sendSuccessBroadcast(uploadCode);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Failed to parse server response", e);
|
||||
sendErrorBroadcast("Failed to parse server response");
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Upload failed, Response code: " + response.code());
|
||||
String errorBody = response.body().string();
|
||||
String errorMsg = "Upload failed, Response code: " + response.code();
|
||||
Log.e(TAG, errorMsg + ", Body: " + errorBody);
|
||||
|
||||
try {
|
||||
JSONObject errorJson = new JSONObject(errorBody);
|
||||
if (errorJson.has("error")) {
|
||||
errorMsg = errorJson.getString("error");
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
// If parsing fails, use the default error message
|
||||
}
|
||||
|
||||
sendErrorBroadcast(errorMsg);
|
||||
}
|
||||
stopSelf();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void sendSuccessBroadcast(String uploadCode) {
|
||||
Intent intent = new Intent(Constant.ACTION_UPLOAD_COMPLETE);
|
||||
intent.putExtra(Constant.EXTRA_UPLOAD_CODE, uploadCode);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
|
||||
private void sendErrorBroadcast(String errorMessage) {
|
||||
Intent intent = new Intent(Constant.ACTION_UPLOAD_ERROR);
|
||||
intent.putExtra(Constant.EXTRA_UPLOAD_ERROR, errorMessage);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.mattintech.simplelogupload;
|
||||
|
||||
import android.app.job.JobParameters;
|
||||
import android.app.job.JobService;
|
||||
import android.content.Intent;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
@@ -10,6 +11,10 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
@@ -33,6 +38,8 @@ public class FileUploadJobService extends JobService {
|
||||
uploadFile(mostRecentFile, params);
|
||||
} else {
|
||||
Toast.makeText(getApplicationContext(), "No DUMPSTATE file found.", Toast.LENGTH_SHORT).show();
|
||||
sendErrorBroadcast("No DUMPSTATE file found");
|
||||
jobFinished(params, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -49,18 +56,36 @@ public class FileUploadJobService extends JobService {
|
||||
.max(Comparator.comparingLong(File::lastModified))
|
||||
.orElse(null) : null;
|
||||
}
|
||||
|
||||
private void uploadFile(File file, JobParameters params) {
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
// Validate file size before upload
|
||||
if (file.length() > Constant.MAX_FILE_SIZE) {
|
||||
Log.e(TAG, "File too large: " + file.length() + " bytes (max: " + Constant.MAX_FILE_SIZE + " bytes)");
|
||||
sendErrorBroadcast("File size exceeds the maximum allowed size of 2GB");
|
||||
jobFinished(params, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create OkHttpClient with timeout configuration for large files
|
||||
OkHttpClient client = new OkHttpClient.Builder()
|
||||
.connectTimeout(60, TimeUnit.SECONDS)
|
||||
.writeTimeout(180, TimeUnit.SECONDS) // 3 minutes timeout for large uploads
|
||||
.readTimeout(60, TimeUnit.SECONDS)
|
||||
.retryOnConnectionFailure(true)
|
||||
.build();
|
||||
|
||||
Log.d(TAG, "Uploading file: " + file.getName() + ", Size: " + file.length());
|
||||
RequestBody fileBody = RequestBody.create(file, MediaType.parse("application/zip"));
|
||||
|
||||
RequestBody fileBody = RequestBody.create(file, MediaType.parse("application/zip"));
|
||||
MultipartBody requestBody = new MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM)
|
||||
.addFormDataPart("file", file.getName(), fileBody)
|
||||
.addFormDataPart(Constant.PARAM_FILE, file.getName(), fileBody)
|
||||
.addFormDataPart(Constant.PARAM_MAX_DOWNLOADS, String.valueOf(Constant.DEFAULT_MAX_DOWNLOADS))
|
||||
.addFormDataPart(Constant.PARAM_EXPIRY_HOURS, String.valueOf(Constant.DEFAULT_EXPIRY_HOURS))
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url("http://172.16.30.69:7777/upload") // Replace with your Flask server's URL
|
||||
.url(Constant.SERVER_URL)
|
||||
.post(requestBody)
|
||||
.build();
|
||||
|
||||
@@ -68,25 +93,59 @@ public class FileUploadJobService extends JobService {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "Upload failed: " + e.getMessage());
|
||||
String errorMsg = "Upload failed: " + e.getMessage();
|
||||
Log.e(TAG, errorMsg);
|
||||
sendErrorBroadcast(errorMsg);
|
||||
jobFinished(params, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
String tinyUrl = response.body().string(); // Assuming the server returns tinyURL in response
|
||||
Log.d(TAG, "Upload successful! TinyURL: " + tinyUrl);
|
||||
|
||||
// Show tinyURL on the UI (using BroadcastReceiver or local storage to communicate with MainActivity)
|
||||
try {
|
||||
String responseBody = response.body().string();
|
||||
Log.d(TAG, "Server response: " + responseBody);
|
||||
|
||||
// Parse JSON response to get the upload code
|
||||
JSONObject jsonResponse = new JSONObject(responseBody);
|
||||
String uploadCode = jsonResponse.getString("code");
|
||||
|
||||
Log.d(TAG, "Upload successful! Code: " + uploadCode);
|
||||
sendSuccessBroadcast(uploadCode);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Failed to parse server response", e);
|
||||
sendErrorBroadcast("Failed to parse server response");
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Upload failed, Response code: " + response.code());
|
||||
String errorBody = response.body().string();
|
||||
String errorMsg = "Upload failed, Response code: " + response.code();
|
||||
Log.e(TAG, errorMsg + ", Body: " + errorBody);
|
||||
|
||||
try {
|
||||
JSONObject errorJson = new JSONObject(errorBody);
|
||||
if (errorJson.has("error")) {
|
||||
errorMsg = errorJson.getString("error");
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
// If parsing fails, use the default error message
|
||||
}
|
||||
|
||||
sendErrorBroadcast(errorMsg);
|
||||
}
|
||||
jobFinished(params, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void sendSuccessBroadcast(String uploadCode) {
|
||||
Intent intent = new Intent(Constant.ACTION_UPLOAD_COMPLETE);
|
||||
intent.putExtra(Constant.EXTRA_UPLOAD_CODE, uploadCode);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
|
||||
private void sendErrorBroadcast(String errorMessage) {
|
||||
Intent intent = new Intent(Constant.ACTION_UPLOAD_ERROR);
|
||||
intent.putExtra(Constant.EXTRA_UPLOAD_ERROR, errorMessage);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,11 @@ import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.job.JobInfo;
|
||||
import android.app.job.JobScheduler;
|
||||
import android.app.job.JobService;
|
||||
import android.app.job.JobParameters;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
@@ -17,6 +18,7 @@ import android.os.Environment;
|
||||
import android.provider.Settings;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.RequiresApi;
|
||||
@@ -31,7 +33,11 @@ public class MainActivity extends Activity {
|
||||
private static final int REQUEST_MANAGE_EXTERNAL_STORAGE = 101;
|
||||
private TextView resultView;
|
||||
private Button uploadButton;
|
||||
private ProgressBar progressBar;
|
||||
private File mostRecentDumpStateFile;
|
||||
|
||||
// BroadcastReceiver to listen for upload results
|
||||
private BroadcastReceiver uploadReceiver;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -40,7 +46,7 @@ public class MainActivity extends Activity {
|
||||
|
||||
resultView = findViewById(R.id.resultView);
|
||||
uploadButton = findViewById(R.id.uploadButton);
|
||||
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
|
||||
// Check for All Files Access Permission
|
||||
requestNotificationPermission();
|
||||
@@ -54,8 +60,50 @@ public class MainActivity extends Activity {
|
||||
if (mostRecentDumpStateFile != null) {
|
||||
//scheduleJob();
|
||||
startFileUpload();
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
uploadButton.setEnabled(false);
|
||||
resultView.setText("Uploading file...");
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize broadcast receiver
|
||||
uploadReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
uploadButton.setEnabled(true);
|
||||
|
||||
if (intent.getAction().equals(Constant.ACTION_UPLOAD_COMPLETE)) {
|
||||
String uploadCode = intent.getStringExtra(Constant.EXTRA_UPLOAD_CODE);
|
||||
showUploadSuccessDialog(uploadCode);
|
||||
} else if (intent.getAction().equals(Constant.ACTION_UPLOAD_ERROR)) {
|
||||
String errorMessage = intent.getStringExtra(Constant.EXTRA_UPLOAD_ERROR);
|
||||
Toast.makeText(MainActivity.this, "Upload Error: " + errorMessage, Toast.LENGTH_LONG).show();
|
||||
resultView.setText("Upload failed: " + errorMessage);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
// Register the broadcast receiver
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Constant.ACTION_UPLOAD_COMPLETE);
|
||||
filter.addAction(Constant.ACTION_UPLOAD_ERROR);
|
||||
registerReceiver(uploadReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
// Unregister the broadcast receiver
|
||||
try {
|
||||
unregisterReceiver(uploadReceiver);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Receiver not registered
|
||||
}
|
||||
}
|
||||
|
||||
private void requestNotificationPermission() {
|
||||
@@ -94,7 +142,7 @@ public class MainActivity extends Activity {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == REQUEST_MANAGE_EXTERNAL_STORAGE) {
|
||||
if (hasAllFilesAccessPermission()) {
|
||||
scheduleJob(); // Now you can proceed if permission is granted
|
||||
checkForDumpStateAndUpdateUI();
|
||||
} else {
|
||||
Toast.makeText(this, "Permission not granted!", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
@@ -138,7 +186,10 @@ public class MainActivity extends Activity {
|
||||
} else {
|
||||
startService(serviceIntent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void showUploadSuccessDialog(String uploadCode) {
|
||||
UploadResultDialog dialog = new UploadResultDialog(this, uploadCode);
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.mattintech.simplelogupload;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class UploadResultDialog extends Dialog {
|
||||
private String uploadCode;
|
||||
|
||||
public UploadResultDialog(Context context, String uploadCode) {
|
||||
super(context);
|
||||
this.uploadCode = uploadCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
setContentView(R.layout.upload_result_dialog);
|
||||
|
||||
TextView codeTextView = findViewById(R.id.uploadCode);
|
||||
codeTextView.setText(uploadCode);
|
||||
|
||||
Button copyButton = findViewById(R.id.copyButton);
|
||||
copyButton.setOnClickListener(v -> {
|
||||
ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText("Upload Code", uploadCode);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
Toast.makeText(getContext(), "Code copied to clipboard", Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.mattintech.simplelogupload.model;
|
||||
|
||||
public class UploadResult {
|
||||
private String code;
|
||||
private String error;
|
||||
|
||||
public UploadResult(String code) {
|
||||
this.code = code;
|
||||
this.error = null;
|
||||
}
|
||||
|
||||
public UploadResult(String error, boolean isError) {
|
||||
this.code = null;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return code != null && !code.isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -27,5 +27,15 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginTop="16dp"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@id/uploadButton"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginTop="16dp"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
55
app/src/main/res/layout/upload_result_dialog.xml
Normal file
55
app/src/main/res/layout/upload_result_dialog.xml
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dialogTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Upload Successful"
|
||||
android:textAlignment="center"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/codeLabel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Your upload code:"
|
||||
android:textAlignment="center"
|
||||
app:layout_constraintTop_toBottomOf="@id/dialogTitle"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/uploadCode"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#007BFF"
|
||||
app:layout_constraintTop_toBottomOf="@id/codeLabel"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/copyButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Copy Code"
|
||||
app:layout_constraintTop_toBottomOf="@id/uploadCode"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,12 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<!-- Allow cleartext traffic to specific server IP -->
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="true">172.16.30.69</domain> <!-- Replace with your server -->
|
||||
</domain-config>
|
||||
<!-- OR: To allow for all domains (for testing purposes only) -->
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="true">172.16.100.167</domain>
|
||||
<!-- Add any other specific servers below if needed -->
|
||||
<domain includeSubdomains="true">localhost</domain>
|
||||
<domain includeSubdomains="true">192.168.1.1</domain>
|
||||
<domain includeSubdomains="true">*.*</domain>
|
||||
<domain includeSubdomains="true">10.0.2.2</domain> <!-- Android emulator localhost -->
|
||||
</domain-config>
|
||||
|
||||
<!-- Base config for all other domains -->
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</network-security-config>
|
||||
|
||||
Reference in New Issue
Block a user