Внедрить обнаружение низкого интернета в AndroidAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Внедрить обнаружение низкого интернета в Android

Сообщение Anonymous »

Я работаю над реализацией обнаружения низкого интернет-соединения в своем приложении. Однако он не работает должным образом — сообщает о «низком интернете», даже если соединение сильное. Я хотел бы реализовать это без использования загрузки файлов, и я был бы очень признателен за ваши рекомендации о том, как надежно обнаружить низкий уровень интернета.
Найдите код, который я реализовал ниже.
Заранее спасибо.
public class NetworkQualityMonitor {

Код: Выделить всё

public interface NetworkQualityCallback {
void onQualityChecked(Quality quality, long latency, double jitter, double packetLoss);
}

public enum Quality {
GOOD, MODERATE, POOR
}

private final OkHttpClient client;
private final String pingUrl = "https://www.google.com";
private final int pingCount;
private final ExecutorService executor;
private final Handler mainHandler;

// --- Caching state ---
private long lastCheckTime = 0;
private Quality lastQuality = Quality.POOR;
private long lastLatency = -1;
private double lastJitter = -1;
private double lastPacketLoss = -1;

private static NetworkQualityMonitor networkQualityMonitor;
private static final long CACHE_DURATION_MS = 7000; // 5 sec

private boolean isChecking = false;               // avoid parallel execution
private boolean isNavigatingToLowNetwork = false; // avoid multiple LowNetworkActivity launches

private NetworkQualityMonitor() {
this.client = new OkHttpClient.Builder().connectTimeout(3, TimeUnit.SECONDS).readTimeout(2, TimeUnit.SECONDS).build();
this.pingCount = 4;
this.executor = Executors.newSingleThreadExecutor();
this.mainHandler = new Handler(Looper.getMainLooper());
}

public synchronized static NetworkQualityMonitor getInstance() {
if (networkQualityMonitor == null) {
networkQualityMonitor = new NetworkQualityMonitor();
}
return networkQualityMonitor;
}

private boolean mapNetworkQuality(Quality quality, long latency, double jitter, double packetLoss) {
return quality == Quality.POOR;
}

public synchronized void checkQuality(Activity activity, boolean isFreshCheck, NetworkChecker.NetworkCheckCallback networkCheckCallback) {
long now = System.currentTimeMillis();

// --- If cached result is still valid, return immediately ---
if (now - lastCheckTime < CACHE_DURATION_MS && !isFreshCheck) {
mainHandler.post(() -> networkCheckCallback.onNetworkCheckCompleted(
lastQuality != Quality.POOR,
lastQuality == Quality.POOR,
0
));
if (lastQuality == Quality.POOR) {
retryCheck(activity, networkCheckCallback); // trigger retry
}
return;
}

runNetworkTest(activity, networkCheckCallback, false);
}

private void runNetworkTest(Activity activity, NetworkChecker.NetworkCheckCallback networkCheckCallback, boolean isRetry) {
executor.execute(() -> {
try {
Quality quality;
List rtts = new ArrayList();
int successCount = 0;

for (int i = 0; i < pingCount; i++) {
long start = System.currentTimeMillis();
Request request = new Request.Builder().url(pingUrl).tag("" + System.currentTimeMillis()).build();

try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
successCount++;
long rtt = System.currentTimeMillis() - start;
rtts.add(rtt);
}
} catch (IOException ignored) {}

try { Thread.sleep(70); } catch (InterruptedException ignored) {}
}

// --- Latency ---
long avgLatency = rtts.isEmpty() ? -1 : rtts.stream().mapToLong(Long::longValue).sum() / rtts.size();

// --- Jitter ---
double jitter = 0;
for (int i = 1; i < rtts.size(); i++) {
jitter += Math.abs(rtts.get(i) - rtts.get(i - 1));
}
jitter = rtts.size() >  1 ? jitter / (rtts.size() - 1) : -1;

// --- Packet Loss ---
double packetLoss = 100.0 * (pingCount - successCount) / pingCount;

// --- Decide Quality ---
quality = decideQuality(avgLatency, jitter, packetLoss);

// --- Cache result ---
lastCheckTime = System.currentTimeMillis();
lastQuality = quality;
lastLatency = avgLatency;
lastJitter = jitter;
lastPacketLoss = packetLoss;

mainHandler.post(() -> {
if (quality == Quality.POOR) {
if (!isRetry) {
// First time poor → retry check
retryCheck(activity, networkCheckCallback);
} else {
// Second time also poor → navigate
networkCheckCallback.onNetworkCheckCompleted(false, true, 0);
navigateToLowNetworkActivity(activity);
}
} else {
networkCheckCallback.onNetworkCheckCompleted(true, false, 0);
}
});

} catch (Exception e) {
mainHandler.post(() -> networkCheckCallback.onNetworkCheckCompleted(true, false, 0));
}
});
}

private void retryCheck(Activity activity, NetworkChecker.NetworkCheckCallback networkCheckCallback) {
// Optional: Add a small delay before retry
mainHandler.postDelayed(() -> runNetworkTest(activity, networkCheckCallback, true), 1000);
}

public void navigateToLowNetworkActivity(Activity activity) {
if (!(activity instanceof SplashActivity) && !(activity instanceof LowNetworkActivity)) {
if (isNavigatingToLowNetwork) return; // already navigating
isNavigatingToLowNetwork = true;

Intent intent = new Intent(activity, LowNetworkActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activity.startActivity(intent);

// Reset flag after a delay (so navigation can happen again later if needed)
mainHandler.postDelayed(() -> isNavigatingToLowNetwork = false, 5000);
}
}

private Quality decideQuality(long latency, double jitter, double packetLoss) {
if (latency == -1 || jitter == -1 || packetLoss == -1) {
return Quality.POOR;
}

boolean good = latency < 1800 && jitter < 1500 && packetLoss < 1;
boolean poor = latency > 1800 || jitter > 1500 || packetLoss > 5;

if (BuildConfig.DEBUG) {
Log.d("NetworkCheck", "Latency : " + latency + " Jitter : " + jitter + " PacketLoss : " + packetLoss);
}

if (good) return Quality.GOOD;
if (poor) return Quality.POOR;
return Quality.MODERATE;
}
}
NetworkQualityMonitor.getInstance().checkQuality(activity, isFreshCall, new NetworkCheckCallback() {
@Override
public void onNetworkCheckCompleted(boolean isConnected, boolean isLowSpeed, doublespeedKbps) {
handleResult(activity, isRunOnUIThread, isSendToNetworkActivity, isLowSpeed, downSpeed, false, прослушиватель);

Подробнее здесь: https://stackoverflow.com/questions/797 ... in-android
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»