Remove dashboard/VPS references - make project PR-ready
- Remove DeviceRegistry.java (dashboard integration) - Remove VPS IP from build.gradle - Remove personal Gitea token from UpdateManager - Add configurable UPDATE_CHECK_URL for updates - Clean README to be generic and PR-ready - Clean update manifests - Remove Docker files and .env from repo
This commit is contained in:
@@ -10,7 +10,7 @@ android {
|
||||
targetSdk 35
|
||||
versionCode 100111
|
||||
versionName "10.1.11"
|
||||
buildConfigField "String", "DEVICE_REGISTRY_URL", '"http://194.163.191.200:4000"'
|
||||
buildConfigField "String", "UPDATE_CHECK_URL", '""'
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
buildToolsVersion "28.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.streamplayer"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.exoplayer:exoplayer:2.8.4'
|
||||
implementation 'androidx.appcompat:appcompat:1.0.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.2'
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
package com.streamplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
|
||||
/**
|
||||
* Informa al dashboard qué dispositivos tienen instalada la app y permite bloquearlos remotamente.
|
||||
*/
|
||||
public class DeviceRegistry {
|
||||
|
||||
public interface Callback {
|
||||
void onAllowed();
|
||||
|
||||
void onBlocked(String reason, String tokenPart);
|
||||
|
||||
void onError(String message);
|
||||
}
|
||||
|
||||
private static final String TAG = "DeviceRegistry";
|
||||
private static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
|
||||
|
||||
private final Context appContext;
|
||||
private final OkHttpClient httpClient;
|
||||
private final ExecutorService executorService;
|
||||
private final Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
public DeviceRegistry(Context context) {
|
||||
this.appContext = context.getApplicationContext();
|
||||
// Usar NetworkUtils para obtener cliente con DNS over HTTPS configurado
|
||||
this.httpClient = NetworkUtils.getClient();
|
||||
this.executorService = Executors.newSingleThreadExecutor();
|
||||
}
|
||||
|
||||
public void syncDevice(Callback callback) {
|
||||
if (TextUtils.isEmpty(BuildConfig.DEVICE_REGISTRY_URL)) {
|
||||
postAllowed(callback);
|
||||
return;
|
||||
}
|
||||
executorService.execute(() -> {
|
||||
try {
|
||||
JSONObject payload = new JSONObject();
|
||||
payload.put("deviceId", getDeviceId());
|
||||
payload.put("deviceName", Build.MODEL);
|
||||
payload.put("model", Build.MODEL);
|
||||
payload.put("manufacturer", capitalize(Build.MANUFACTURER));
|
||||
payload.put("osVersion", Build.VERSION.RELEASE + " (API " + Build.VERSION.SDK_INT + ")");
|
||||
payload.put("appVersionName", BuildConfig.VERSION_NAME);
|
||||
payload.put("appVersionCode", BuildConfig.VERSION_CODE);
|
||||
|
||||
String endpoint = sanitizeBaseUrl(BuildConfig.DEVICE_REGISTRY_URL) + "/api/devices/register";
|
||||
RequestBody body = RequestBody.create(payload.toString(), JSON);
|
||||
Request request = new Request.Builder()
|
||||
.url(endpoint)
|
||||
.post(body)
|
||||
.build();
|
||||
try (Response response = httpClient.newCall(request).execute()) {
|
||||
if (!response.isSuccessful() || response.body() == null) {
|
||||
throw new IOException("HTTP " + response.code());
|
||||
}
|
||||
String responseText = response.body().string();
|
||||
|
||||
// Validar que no sea HTML antes de parsear
|
||||
if (responseText != null) {
|
||||
String trimmed = responseText.trim();
|
||||
if (trimmed.startsWith("<!") || trimmed.startsWith("<html")) {
|
||||
throw new IOException("El servidor devolvió HTML en lugar de JSON");
|
||||
}
|
||||
}
|
||||
|
||||
JSONObject json = new JSONObject(responseText);
|
||||
JSONObject deviceJson = json.optJSONObject("device");
|
||||
JSONObject verificationJson = json.optJSONObject("verification");
|
||||
boolean blocked = json.optBoolean("blocked", false);
|
||||
String reason = json.optString("message");
|
||||
if (TextUtils.isEmpty(reason) && deviceJson != null) {
|
||||
reason = deviceJson.optString("notes", "");
|
||||
}
|
||||
String tokenPart = "";
|
||||
if (verificationJson != null) {
|
||||
boolean verificationRequired = verificationJson.optBoolean("required", false);
|
||||
blocked = blocked || verificationRequired;
|
||||
tokenPart = verificationJson.optString("clientTokenPart", "");
|
||||
}
|
||||
if (blocked) {
|
||||
postBlocked(callback, reason, tokenPart);
|
||||
} else {
|
||||
postAllowed(callback);
|
||||
}
|
||||
}
|
||||
} catch (IOException | JSONException e) {
|
||||
Log.w(TAG, "Device sync error", e);
|
||||
postError(callback, e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String sanitizeBaseUrl(String base) {
|
||||
if (TextUtils.isEmpty(base)) {
|
||||
return "";
|
||||
}
|
||||
if (base.endsWith("/")) {
|
||||
return base.substring(0, base.length() - 1);
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
private String getDeviceId() {
|
||||
String id = Settings.Secure.getString(appContext.getContentResolver(),
|
||||
Settings.Secure.ANDROID_ID);
|
||||
if (TextUtils.isEmpty(id)) {
|
||||
id = Build.MODEL + "-" + Build.BOARD + "-" + BuildConfig.VERSION_CODE;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
private String capitalize(String value) {
|
||||
if (TextUtils.isEmpty(value)) {
|
||||
return "";
|
||||
}
|
||||
return value.substring(0, 1).toUpperCase(Locale.getDefault())
|
||||
+ value.substring(1);
|
||||
}
|
||||
|
||||
public void release() {
|
||||
executorService.shutdownNow();
|
||||
}
|
||||
|
||||
private void postAllowed(Callback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
mainHandler.post(callback::onAllowed);
|
||||
}
|
||||
|
||||
private void postBlocked(Callback callback, String reason, String tokenPart) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
String reasonText = reason == null ? "" : reason;
|
||||
String token = tokenPart == null ? "" : tokenPart;
|
||||
mainHandler.post(() -> callback.onBlocked(reasonText, token));
|
||||
}
|
||||
|
||||
private void postError(Callback callback, String message) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
mainHandler.post(() -> callback.onError(message));
|
||||
}
|
||||
}
|
||||
@@ -52,8 +52,6 @@ public class MainActivity extends AppCompatActivity {
|
||||
private SectionEntry currentSection;
|
||||
private UpdateManager updateManager;
|
||||
private AlertDialog updateDialog;
|
||||
private AlertDialog blockedDialog;
|
||||
private DeviceRegistry deviceRegistry;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -122,28 +120,6 @@ public class MainActivity extends AppCompatActivity {
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
deviceRegistry = new DeviceRegistry(this);
|
||||
deviceRegistry.syncDevice(new DeviceRegistry.Callback() {
|
||||
@Override
|
||||
public void onAllowed() {
|
||||
// Device authorized, continue normally.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlocked(String reason, String tokenPart) {
|
||||
showBlockedDialog(reason, tokenPart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String message) {
|
||||
if (!TextUtils.isEmpty(message)) {
|
||||
Toast.makeText(MainActivity.this,
|
||||
getString(R.string.device_registry_error, message),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -160,15 +136,9 @@ public class MainActivity extends AppCompatActivity {
|
||||
if (updateDialog != null && updateDialog.isShowing()) {
|
||||
updateDialog.dismiss();
|
||||
}
|
||||
if (blockedDialog != null && blockedDialog.isShowing()) {
|
||||
blockedDialog.dismiss();
|
||||
}
|
||||
if (updateManager != null) {
|
||||
updateManager.release();
|
||||
}
|
||||
if (deviceRegistry != null) {
|
||||
deviceRegistry.release();
|
||||
}
|
||||
}
|
||||
|
||||
private void selectSection(int index) {
|
||||
@@ -348,54 +318,6 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private void showBlockedDialog(String reason, String tokenPart) {
|
||||
if (isFinishing()) {
|
||||
return;
|
||||
}
|
||||
String finalReason = TextUtils.isEmpty(reason)
|
||||
? getString(R.string.device_blocked_default_reason)
|
||||
: reason;
|
||||
if (blockedDialog != null && blockedDialog.isShowing()) {
|
||||
blockedDialog.dismiss();
|
||||
}
|
||||
View dialogView = getLayoutInflater().inflate(R.layout.dialog_blocked, null);
|
||||
TextView messageText = dialogView.findViewById(R.id.blocked_message_text);
|
||||
View tokenContainer = dialogView.findViewById(R.id.blocked_token_container);
|
||||
TextView tokenValue = dialogView.findViewById(R.id.blocked_token_value);
|
||||
messageText.setText(getString(R.string.device_blocked_message, finalReason));
|
||||
boolean hasToken = !TextUtils.isEmpty(tokenPart);
|
||||
if (hasToken) {
|
||||
tokenContainer.setVisibility(View.VISIBLE);
|
||||
tokenValue.setText(tokenPart);
|
||||
tokenValue.setOnClickListener(v -> copyTokenToClipboard(tokenPart));
|
||||
} else {
|
||||
tokenContainer.setVisibility(View.GONE);
|
||||
}
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.ThemeOverlay_StreamPlayer_AlertDialog)
|
||||
.setTitle(R.string.device_blocked_title)
|
||||
.setView(dialogView)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(R.string.device_blocked_close,
|
||||
(dialog, which) -> finish());
|
||||
if (hasToken) {
|
||||
builder.setNeutralButton(R.string.device_blocked_copy_token,
|
||||
(dialog, which) -> copyTokenToClipboard(tokenPart));
|
||||
}
|
||||
blockedDialog = builder.create();
|
||||
blockedDialog.show();
|
||||
}
|
||||
|
||||
private void copyTokenToClipboard(String tokenPart) {
|
||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
if (clipboard == null) {
|
||||
Toast.makeText(this, R.string.device_blocked_copy_error, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
ClipData data = ClipData.newPlainText("token", tokenPart);
|
||||
clipboard.setPrimaryClip(data);
|
||||
Toast.makeText(this, R.string.device_blocked_copy_success, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
private void toggleVpn() {
|
||||
VpnManager vpnManager = VpnManager.getInstance();
|
||||
if (vpnManager.isConnected()) {
|
||||
|
||||
@@ -43,9 +43,12 @@ import okhttp3.Response;
|
||||
public class UpdateManager {
|
||||
|
||||
private static final String TAG = "UpdateManager";
|
||||
// NOTE: Configure tu propia URL de releases en build.gradle o aquí
|
||||
private static final String LATEST_RELEASE_URL =
|
||||
"https://gitea.cbcren.online/api/v1/repos/renato97/app/releases/latest";
|
||||
private static final String GITEA_TOKEN = "4b94b3610136529861af0821040a801906821a0f";
|
||||
BuildConfig.UPDATE_CHECK_URL.isEmpty()
|
||||
? "https://your-gitea-instance.com/api/v1/repos/your-user/your-repo/releases/latest"
|
||||
: BuildConfig.UPDATE_CHECK_URL;
|
||||
private static final String GITEA_TOKEN = ""; // Configura tu token si es necesario
|
||||
|
||||
private final Context appContext;
|
||||
private final Handler mainHandler;
|
||||
|
||||
Reference in New Issue
Block a user