adding settings screen

This commit is contained in:
2025-04-15 09:52:20 -04:00
parent 0a4f7871bc
commit e36d0616d5
10 changed files with 442 additions and 210 deletions

View File

@@ -54,6 +54,17 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".view.MainActivity" />
</activity>
<!-- Settings Activity -->
<activity
android:name=".view.SettingsActivity"
android:label="Settings"
android:parentActivityName=".view.MainActivity"
android:exported="false">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".view.MainActivity" />
</activity>
<!-- File Upload Foreground Service -->
<service

View File

@@ -4,14 +4,18 @@ package com.mattintech.simplelogupload.constant;
* Network-related constants
*/
public class NetworkConstants {
// Server constants
public static final String SERVER_URL = "http://172.16.100.167:7777/upload";
// These URL constants are now dynamically set in getServerUrl()
// via PreferencesUtil to allow for customization
public static final String SERVER_URL_BASE = "/upload";
// 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";
// Authentication
public static final String CLIENT_KEY_HEADER = "client-key";
// Default values
public static final int DEFAULT_MAX_DOWNLOADS = 1;
public static final int DEFAULT_EXPIRY_HOURS = 24;

View File

@@ -11,6 +11,7 @@ import com.mattintech.simplelogupload.db.UploadHistoryRepository;
import com.mattintech.simplelogupload.model.UploadHistory;
import com.mattintech.simplelogupload.model.UploadResult;
import com.mattintech.simplelogupload.service.FileUploadForegroundService;
import com.mattintech.simplelogupload.util.PreferencesUtil;
import java.io.File;
import java.io.IOException;
@@ -103,10 +104,20 @@ public class UploadController {
.addFormDataPart(NetworkConstants.PARAM_EXPIRY_HOURS, String.valueOf(expiryHours))
.build();
// Get server URL and client key from preferences
String serverUrl = PreferencesUtil.getServerUrl(context);
String clientKey = PreferencesUtil.getClientKey(context);
Log.d(TAG, "Using server URL: " + serverUrl);
// Build request with client-key header
Request request = new Request.Builder()
.url(NetworkConstants.SERVER_URL)
.url(serverUrl)
.header(NetworkConstants.CLIENT_KEY_HEADER, clientKey)
.post(requestBody)
.build();
Log.d(TAG, "Sending upload request with " + NetworkConstants.CLIENT_KEY_HEADER + " header");
client.newCall(request).enqueue(new Callback() {
@Override
@@ -142,8 +153,16 @@ public class UploadController {
}
} else {
String errorBody = response.body().string();
String errorMsg = "Upload failed, Response code: " + response.code();
Log.e(TAG, errorMsg + ", Body: " + errorBody);
String errorMsg;
// Check for authentication errors
if (response.code() == 401 || response.code() == 403) {
errorMsg = "Authentication failed. Please check client key.";
Log.e(TAG, "Authentication error: " + response.code() + ", Body: " + errorBody);
} else {
errorMsg = "Upload failed, Response code: " + response.code();
Log.e(TAG, errorMsg + ", Body: " + errorBody);
}
try {
JSONObject errorJson = new JSONObject(errorBody);

View File

@@ -0,0 +1,116 @@
package com.mattintech.simplelogupload.util;
import android.content.Context;
import android.content.SharedPreferences;
/**
* Utility class for handling application preferences
*/
public class PreferencesUtil {
private static final String PREFERENCES_NAME = "SimpleLogUploadPrefs";
// Preference keys
public static final String KEY_SERVER_ADDRESS = "server_address";
public static final String KEY_SERVER_PORT = "server_port";
public static final String KEY_CLIENT_KEY = "client_key";
// Default values
private static final String DEFAULT_SERVER_ADDRESS = "172.16.100.167";
private static final int DEFAULT_SERVER_PORT = 7777;
private static final String DEFAULT_CLIENT_KEY = "default-secret-key";
/**
* Get the shared preferences instance
*
* @param context The application context
* @return The SharedPreferences instance
*/
private static SharedPreferences getPreferences(Context context) {
return context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
}
/**
* Get the server address from preferences
*
* @param context The application context
* @return The server address
*/
public static String getServerAddress(Context context) {
return getPreferences(context).getString(KEY_SERVER_ADDRESS, DEFAULT_SERVER_ADDRESS);
}
/**
* Set the server address in preferences
*
* @param context The application context
* @param serverAddress The server address to save
*/
public static void setServerAddress(Context context, String serverAddress) {
getPreferences(context).edit().putString(KEY_SERVER_ADDRESS, serverAddress).apply();
}
/**
* Get the server port from preferences
*
* @param context The application context
* @return The server port
*/
public static int getServerPort(Context context) {
return getPreferences(context).getInt(KEY_SERVER_PORT, DEFAULT_SERVER_PORT);
}
/**
* Set the server port in preferences
*
* @param context The application context
* @param serverPort The server port to save
*/
public static void setServerPort(Context context, int serverPort) {
getPreferences(context).edit().putInt(KEY_SERVER_PORT, serverPort).apply();
}
/**
* Get the client key from preferences
*
* @param context The application context
* @return The client key
*/
public static String getClientKey(Context context) {
return getPreferences(context).getString(KEY_CLIENT_KEY, DEFAULT_CLIENT_KEY);
}
/**
* Set the client key in preferences
*
* @param context The application context
* @param clientKey The client key to save
*/
public static void setClientKey(Context context, String clientKey) {
getPreferences(context).edit().putString(KEY_CLIENT_KEY, clientKey).apply();
}
/**
* Get the complete server URL (address + port + path)
*
* @param context The application context
* @return The complete server URL
*/
public static String getServerUrl(Context context) {
String address = getServerAddress(context);
int port = getServerPort(context);
return "http://" + address + ":" + port + "/upload";
}
/**
* Reset all settings to default values
*
* @param context The application context
*/
public static void resetToDefaults(Context context) {
SharedPreferences.Editor editor = getPreferences(context).edit();
editor.putString(KEY_SERVER_ADDRESS, DEFAULT_SERVER_ADDRESS);
editor.putInt(KEY_SERVER_PORT, DEFAULT_SERVER_PORT);
editor.putString(KEY_CLIENT_KEY, DEFAULT_CLIENT_KEY);
editor.apply();
}
}

View File

@@ -305,6 +305,10 @@ public class MainActivity extends AppCompatActivity {
// Open upload history activity
startActivity(new Intent(this, UploadHistoryActivity.class));
return true;
} else if (id == R.id.action_settings) {
// Open settings activity
startActivity(new Intent(this, SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);

View File

@@ -0,0 +1,128 @@
package com.mattintech.simplelogupload.view;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Button;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.textfield.TextInputEditText;
import com.mattintech.simplelogupload.R;
import com.mattintech.simplelogupload.constant.AppConstants;
import com.mattintech.simplelogupload.util.PreferencesUtil;
/**
* Activity for application settings
*/
public class SettingsActivity extends AppCompatActivity {
private static final String TAG = AppConstants.APP_TAG + "SettingsActivity";
private TextInputEditText serverAddressInput;
private TextInputEditText serverPortInput;
private TextInputEditText clientKeyInput;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
// Initialize UI components
serverAddressInput = findViewById(R.id.serverAddressInput);
serverPortInput = findViewById(R.id.serverPortInput);
clientKeyInput = findViewById(R.id.clientKeyInput);
Button saveButton = findViewById(R.id.saveSettingsButton);
Button resetButton = findViewById(R.id.resetSettingsButton);
// Set up action bar
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("Settings");
}
// Load current settings
loadSettings();
// Set up button click listeners
saveButton.setOnClickListener(v -> saveSettings());
resetButton.setOnClickListener(v -> resetSettings());
}
/**
* Load current settings from SharedPreferences
*/
private void loadSettings() {
serverAddressInput.setText(PreferencesUtil.getServerAddress(this));
serverPortInput.setText(String.valueOf(PreferencesUtil.getServerPort(this)));
clientKeyInput.setText(PreferencesUtil.getClientKey(this));
}
/**
* Save settings to SharedPreferences
*/
private void saveSettings() {
try {
// Get values from input fields
String serverAddress = serverAddressInput.getText().toString().trim();
String serverPortStr = serverPortInput.getText().toString().trim();
String clientKey = clientKeyInput.getText().toString().trim();
// Validate input
if (TextUtils.isEmpty(serverAddress)) {
serverAddressInput.setError("Server address is required");
return;
}
if (TextUtils.isEmpty(serverPortStr)) {
serverPortInput.setError("Server port is required");
return;
}
int serverPort;
try {
serverPort = Integer.parseInt(serverPortStr);
if (serverPort <= 0 || serverPort > 65535) {
serverPortInput.setError("Port must be between 1 and 65535");
return;
}
} catch (NumberFormatException e) {
serverPortInput.setError("Invalid port number");
return;
}
if (TextUtils.isEmpty(clientKey)) {
clientKeyInput.setError("Client key is required");
return;
}
// Save settings
PreferencesUtil.setServerAddress(this, serverAddress);
PreferencesUtil.setServerPort(this, serverPort);
PreferencesUtil.setClientKey(this, clientKey);
Log.d(TAG, "Settings saved successfully");
Toast.makeText(this, "Settings saved successfully", Toast.LENGTH_SHORT).show();
finish();
} catch (Exception e) {
Log.e(TAG, "Error saving settings", e);
Toast.makeText(this, "Error saving settings: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
/**
* Reset settings to default values
*/
private void resetSettings() {
PreferencesUtil.resetToDefaults(this);
loadSettings();
Toast.makeText(this, "Settings reset to defaults", Toast.LENGTH_SHORT).show();
}
@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
}

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Server Configuration"
android:textSize="20sp"
android:textStyle="bold"
android:layout_marginBottom="16dp" />
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="Server Address">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/serverAddressInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="Server Port">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/serverPortInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" />
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Authentication"
android:textSize="20sp"
android:textStyle="bold"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp" />
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="Client Key"
app:endIconMode="password_toggle">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/clientKeyInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/saveSettingsButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Save Settings"
android:layout_marginTop="16dp" />
<Button
android:id="@+id/resetSettingsButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Reset to Defaults"
android:layout_marginTop="8dp"
style="@style/Widget.AppCompat.Button.Borderless.Colored" />
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,64 @@
<?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="match_parent"
android:padding="24dp">
<ImageView
android:id="@+id/logoImage"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_marginTop="32dp"
android:src="@android:drawable/ic_menu_upload"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/welcomeTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Welcome to SimpleLogUpload"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/logoImage" />
<TextView
android:id="@+id/welcomeDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="Before you can use this app, you need to configure it to connect to your SimpleLogUpload server instance."
android:textAlignment="center"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/welcomeTitle" />
<TextView
android:id="@+id/welcomeDetails"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="The app requires:\n\n• Server Address - IP or hostname of your server\n• Server Port - Port your server is running on\n• Client Key - Authentication key for secure uploads\n\nYour administrator should have provided these details."
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/welcomeDescription" />
<Button
android:id="@+id/nextButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="Continue to Setup"
android:padding="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -5,4 +5,9 @@
android:title="Upload History"
android:orderInCategory="100"
android:showAsAction="never" />
<item
android:id="@+id/action_settings"
android:title="Settings"
android:orderInCategory="200"
android:showAsAction="never" />
</menu>