diff --git a/app/build.gradle b/app/build.gradle index e1eb950..6ecc0a0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,6 +26,19 @@ android { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } + flavorDimensions += "version" + productFlavors { + free { + dimension "version" + applicationIdSuffix ".free" + versionNameSuffix "-free" + } + pro { + dimension "version" + applicationIdSuffix ".pro" + versionNameSuffix "-pro" + } + } } dependencies { diff --git a/app/src/free/java/me/sergiotarxz/bedrockstation/Premium.java b/app/src/free/java/me/sergiotarxz/bedrockstation/Premium.java new file mode 100644 index 0000000..f1a376d --- /dev/null +++ b/app/src/free/java/me/sergiotarxz/bedrockstation/Premium.java @@ -0,0 +1,4 @@ +package me.sergiotarxz.bedrockstation; +public class Premium { + public static boolean ENABLED = false; +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5e88685..2a3a034 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,6 +17,10 @@ android:theme="@style/Theme.BedrockStation" tools:targetApi="31"> + + diff --git a/app/src/main/java/me/sergiotarxz/bedrockstation/CountDownStartProxy.java b/app/src/main/java/me/sergiotarxz/bedrockstation/CountDownStartProxy.java new file mode 100644 index 0000000..2abc639 --- /dev/null +++ b/app/src/main/java/me/sergiotarxz/bedrockstation/CountDownStartProxy.java @@ -0,0 +1,100 @@ +package me.sergiotarxz.bedrockstation; + +import android.os.Bundle; + +import androidx.activity.EdgeToEdge; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; +import android.widget.LinearLayout; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.view.View; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.Gravity; +import android.database.sqlite.SQLiteDatabase; +import android.view.ViewGroup.LayoutParams; +import android.content.Intent; +import me.sergiotarxz.bedrockstation.ProxyService; +import me.sergiotarxz.bedrockstation.Options; +import me.sergiotarxz.bedrockstation.DB; +import android.widget.Toast; +import androidx.activity.result.contract.ActivityResultContracts.RequestPermission; +import androidx.activity.result.ActivityResultLauncher; +import android.app.NotificationManager; +import android.content.ServiceConnection; +import android.content.Context; +import android.content.ComponentName; +import android.os.IBinder; +import android.util.TypedValue; +import java.util.List; +import me.sergiotarxz.bedrockstation.Servers; +import me.sergiotarxz.bedrockstation.Server; +import android.app.AlertDialog; +import android.content.DialogInterface; +import me.sergiotarxz.bedrockstation.Premium; +import java.util.Timer; +import java.util.TimerTask; +import android.os.Handler; +import android.os.Message; + +public class CountDownStartProxy extends AppCompatActivity { + static int SECONDS = 5; + int seconds = SECONDS; + TextView secondsToWaitTextView; + Timer timer; + int messageNumber = 0; + static AppCompatActivity activity; + @Override + protected void onStart() { + super.onStart(); + seconds = SECONDS; + timer = new Timer(); + timer.scheduleAtFixedRate(new TimerTask() { + public void run() { + finishTimerHandler.post(new Runnable() { + @Override + public void run() { + seconds--; + if (seconds < 0) { + Intent intent = new Intent(CountDownStartProxy.this, ProxyService.class); + CountDownStartProxy.this.startForegroundService(intent); + timer.cancel(); + onBackPressed(); + return; + } + secondsToWaitTextView.setText(seconds+""); + } + }); + } + }, 1000, 1000 + ); + } + + private final Handler finishTimerHandler = new Handler(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + activity = this; + LinearLayout layout = new LinearLayout(this); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT); + layout.setLayoutParams(layoutParams); + layoutParams.setMargins(100, 100, 100, 100); + layout.setOrientation(LinearLayout.VERTICAL); + TextView explain = new TextView(this); + explain.setText("You must wait before starting the Bedrock Proxy or update to premium"); + secondsToWaitTextView = new TextView(this); + secondsToWaitTextView.setText(seconds + ""); + secondsToWaitTextView.setGravity(Gravity.CENTER_HORIZONTAL); + secondsToWaitTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, 70); + layout.addView(explain); + layout.addView(secondsToWaitTextView); + setContentView(layout); + } +} diff --git a/app/src/main/java/me/sergiotarxz/bedrockstation/MainActivity.java b/app/src/main/java/me/sergiotarxz/bedrockstation/MainActivity.java index 5c030fe..c352cc2 100644 --- a/app/src/main/java/me/sergiotarxz/bedrockstation/MainActivity.java +++ b/app/src/main/java/me/sergiotarxz/bedrockstation/MainActivity.java @@ -33,6 +33,9 @@ import android.util.TypedValue; import java.util.List; import me.sergiotarxz.bedrockstation.Servers; import me.sergiotarxz.bedrockstation.Server; +import android.app.AlertDialog; +import android.content.DialogInterface; +import me.sergiotarxz.bedrockstation.Premium; public class MainActivity extends AppCompatActivity { interface Lambda { @@ -135,7 +138,6 @@ public class MainActivity extends AppCompatActivity { LayoutParams.MATCH_PARENT); layoutParams.setMargins(100, 100, 100, 100); layout.setLayoutParams(layoutParams); -// layout.setGravity(Gravity.CENTER_HORIZONTAL); layout.setId(1); SQLiteDatabase db = new DB(this).getInstance(); options = new Options(db); @@ -152,7 +154,7 @@ public class MainActivity extends AppCompatActivity { directConnectionButton = new Button(this); directConnectionButton.setOnClickListener( (View view) -> { - if(!serverStarted) { + if(!proxyService.isServerStarted()) { if (!getSystemService(NotificationManager.class) .areNotificationsEnabled()) { requestPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS); @@ -160,7 +162,11 @@ public class MainActivity extends AppCompatActivity { } options.set(Options.HOST_SELECTED, options.get(Options.HOST_CACHE)); options.set(Options.PORT_SELECTED, options.get(Options.PORT_CACHE)); - startServiceProxy(); + if (Premium.ENABLED) { + startServiceProxy(); + } + Intent intent = new Intent(this, CountDownStartProxy.class); + startActivity(intent); return; } finishServiceProxy(); @@ -179,7 +185,6 @@ public class MainActivity extends AppCompatActivity { editTextLayoutParams.width = 500; directConnectionButton.setLayoutParams(buttonLayoutParams); LinearLayout hostLayout = new LinearLayout(this); -// hostLayout.setGravity(Gravity.CENTER_HORIZONTAL); TextView hostIndicator = new TextView(this); hostIndicator.setText("IP: "); hostEditText = new EditText(this); @@ -192,7 +197,6 @@ public class MainActivity extends AppCompatActivity { hostLayout.addView(hostIndicator); hostLayout.addView(hostEditText); LinearLayout portLayout = new LinearLayout(this); -// portLayout.setGravity(Gravity.CENTER_HORIZONTAL); TextView portIndicator = new TextView(this); portEditText = new EditText(this); onChangeEditText(portEditText, () -> { @@ -266,23 +270,27 @@ public class MainActivity extends AppCompatActivity { center(portLayout); Button create = new Button(this); create.setOnClickListener( (View view) -> { + if (!Premium.ENABLED) { + alertSomethingWrong("Payment required", "You need premium to add new servers"); + return; + } int port; String title; String host; try { port = Integer.parseInt(portEdit.getText().toString()); } catch (Exception e) { - Toast.makeText(this, "Port must be a number", Toast.LENGTH_LONG).show(); + alertSomethingWrong("Invalid data", "Port must be a number"); return; } title = titleEdit.getText().toString(); host = hostEdit.getText().toString(); - if (host.indexOf("\n") != -1) { - Toast.makeText(this, "Invalid host", Toast.LENGTH_LONG).show(); + if (host.indexOf("\n") != -1 || host.equals("") || host.indexOf(" ") != -1) { + alertSomethingWrong("Invalid data", "Not a valid host"); return; } if (title.indexOf("\n") != -1) { - Toast.makeText(this, "Invalid title", Toast.LENGTH_LONG).show(); + alertSomethingWrong("Invalid data", "Not a valid title"); return; } servers.add(new Server(title, host, port)); @@ -341,8 +349,17 @@ public class MainActivity extends AppCompatActivity { startServiceProxy(); }); delete.setOnClickListener( (View view) -> { - servers.delete(server); - fillServerList(null, servers); + new AlertDialog.Builder(this) + .setTitle("Delete server") + .setMessage("Are you sure you want to delete this server?") + .setPositiveButton("Delete server", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + servers.delete(server); + fillServerList(null, servers); + } + }) + .setNegativeButton("Keep server", null) + .show(); }); buttons.addView(delete); serverListInnerLayout.addView(buttons); @@ -354,19 +371,30 @@ public class MainActivity extends AppCompatActivity { } private void center(TextView view) { -// view.setGravity(Gravity.CENTER_HORIZONTAL); } private void center(LinearLayout view) { -// view.setGravity(Gravity.CENTER_HORIZONTAL); + } + + private void alertSomethingWrong(String title, String message) { + new AlertDialog.Builder(this) + .setTitle(title) + .setMessage(message) + + .setPositiveButton("Accept", null) + .show(); } private ActivityResultLauncher requestPermissionLauncher = registerForActivityResult(new RequestPermission(), isGranted -> { if (isGranted) { - startServiceProxy(); + if (Premium.ENABLED) { + startServiceProxy(); + } + Intent intent = new Intent(this, CountDownStartProxy.class); + startActivity(intent); } else { - Toast.makeText(this, "You need notifications to run the proxy", Toast.LENGTH_LONG).show(); + alertSomethingWrong("Notifications not enabled", "You need notifications to run the proxy"); } }); diff --git a/app/src/main/java/me/sergiotarxz/bedrockstation/ProxyService.java b/app/src/main/java/me/sergiotarxz/bedrockstation/ProxyService.java index ee2d69b..651ef75 100644 --- a/app/src/main/java/me/sergiotarxz/bedrockstation/ProxyService.java +++ b/app/src/main/java/me/sergiotarxz/bedrockstation/ProxyService.java @@ -18,6 +18,7 @@ import android.database.sqlite.SQLiteDatabase; import me.sergiotarxz.bedrockstation.DB; import android.widget.Toast; import android.os.StrictMode; +import android.app.AlertDialog; import me.sergiotarxz.bedrockstation.ProxyThread; @@ -27,7 +28,7 @@ public class ProxyService extends Service { Thread proxyThread = null; public class LocalBinder extends Binder { - ProxyService getService() { + public ProxyService getService() { return ProxyService.this; } } @@ -51,8 +52,8 @@ public class ProxyService extends Service { } public class Action { - static final String START = "start"; - static final String END = "end"; + public static final String START = "start"; + public static final String END = "end"; } @Override @@ -101,7 +102,6 @@ public class ProxyService extends Service { startServer(); } if (intent.getAction() == Action.END) { - Log.w("bedrockstation", "HOLA"); finishServer(); stopForeground(true); } @@ -114,6 +114,7 @@ public class ProxyService extends Service { public void finishServer() { if (isServerStarted()) { + Log.e("bedrockstation", "FINISHING SERVER"); ((ProxyThread) proxyThread).terminate(); try { proxyThread.join(); @@ -131,9 +132,22 @@ public class ProxyService extends Service { throw new RuntimeException(e.toString()); } } + private void alertSomethingWrong(String title, String message) { +// if (!isFinishing()) { +// new AlertDialog.Builder(this) +// .setTitle(title) +// .setMessage(message) +// +// // Specifying a listener allows you to take an action before dismissing the dialog. +// // The dialog is automatically dismissed when a dialog button is clicked. +// .setPositiveButton("accept", null) +// .show(); +// } + } public void startServer() { if (!isServerStarted()) { + Log.e("bedrockstation", "STARTING SERVER"); Options options = new Options(new DB(this).getInstance()); String host = options.get(Options.HOST_SELECTED); @@ -147,9 +161,13 @@ public class ProxyService extends Service { } StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); - createServer(new InetSocketAddress(host, port)); - proxyThread.start(); - activity.onStartProxyService(); + try { + createServer(new InetSocketAddress(host, port)); + proxyThread.start(); + activity.onStartProxyService(); + } catch (Exception e) { + alertSomethingWrong("Invalid server address", "The server address is malformed"); + } } } } diff --git a/app/src/main/java/me/sergiotarxz/bedrockstation/ProxyThread.java b/app/src/main/java/me/sergiotarxz/bedrockstation/ProxyThread.java index 22d9372..39fb4b0 100644 --- a/app/src/main/java/me/sergiotarxz/bedrockstation/ProxyThread.java +++ b/app/src/main/java/me/sergiotarxz/bedrockstation/ProxyThread.java @@ -65,7 +65,7 @@ public class ProxyThread extends Thread } server.close(); } catch (Exception e) { - throw new RuntimeException(Log.getStackTraceString(e)); + Log.w("me.sergiotarxz.bedrockstation", Log.getStackTraceString(e)); } } diff --git a/app/src/pro/java/me/sergiotarxz/bedrockstation/Premium.java b/app/src/pro/java/me/sergiotarxz/bedrockstation/Premium.java new file mode 100644 index 0000000..2cc2641 --- /dev/null +++ b/app/src/pro/java/me/sergiotarxz/bedrockstation/Premium.java @@ -0,0 +1,4 @@ +package me.sergiotarxz.bedrockstation; +public class Premium { + public static boolean ENABLED = true; +}