Internet Speed Monitoring Service

package com.saud_khan_dev.speed_test.backend.services;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Icon;
import android.net.TrafficStats;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;

import com.saud_khan_dev.speed_test.MyApp;
import com.saud_khan_dev.speed_test.PrefHelper.AppSharedPref;
import com.saud_khan_dev.speed_test.R;
import com.saud_khan_dev.speed_test.ui.activities.MainActivity;

import java.util.Locale;

/**
* Author: Muhammad Saud khan
*/

public class
SpeedMonitorService extends IntentService {

private final int mNotificationId = 1;
private Handler mHandler;
private Notification.Builder mBuilder;
private NotificationManager mNotifyMgr;
private String mDownloadSpeedOutput;
private String mUnits;
private boolean mDestroyed = false;
AppSharedPref pref;
public SpeedMonitorService() {
super("SpeedMonitorService");
}

@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onHandleIntent(Intent intent) {

/*Check first if meter is disabled, in which you don't start the service*/
pref=new AppSharedPref(getApplicationContext());

boolean state =pref.isSpeedMonitoringEnable();
createNotificationChannel();
initializeNotification();

while (!mDestroyed && state == true) {

getDownloadSpeed();

Message completeMessage = mHandler.obtainMessage(1);
completeMessage.sendToTarget();

}
}


private void initializeNotification() {

mHandler = new Handler(Looper.getMainLooper()) {

@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void handleMessage(Message inputMessage) {

if (mDestroyed) {
return;
}

Bitmap bitmap = createBitmapFromString(mDownloadSpeedOutput, mUnits);

Icon icon = Icon.createWithBitmap(bitmap);

mBuilder.setSmallIcon(icon);

mNotifyMgr.notify(mNotificationId, mBuilder.build());

}

};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mBuilder = new Notification.Builder(this,MyApp.CHANNEL_ID);
}else {
mBuilder = new Notification.Builder(this);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mBuilder.setSmallIcon(Icon.createWithBitmap(createBitmapFromString("0", " KB")));
}else {
int icon2 = getResources().getIdentifier("0\nKB", "drawable", getPackageName());
mBuilder.setSmallIcon(icon2);
}
mBuilder.setContentTitle("");
mBuilder.setVisibility(Notification.VISIBILITY_SECRET);
if (Build.VERSION.SDK_INT >= 21) {
mBuilder.setVisibility(Notification.VISIBILITY_PUBLIC);
}
mBuilder.setOngoing(true);

/*Creates a special PendingIntent so that the app will open when the notification window
is tapped*/
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent
.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(pendingIntent);


mNotifyMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotifyMgr.notify(mNotificationId, mBuilder.build());

startForeground(mNotificationId, mBuilder.build());

}

private Bitmap createBitmapFromString(String speed, String units) {

Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(55);
paint.setTextAlign(Paint.Align.CENTER);

Paint unitsPaint = new Paint();
unitsPaint.setAntiAlias(true);
unitsPaint.setTextSize(40); // size is in pixels
unitsPaint.setTextAlign(Paint.Align.CENTER);

Rect textBounds = new Rect();
paint.getTextBounds(speed, 0, speed.length(), textBounds);

Rect unitsTextBounds = new Rect();
unitsPaint.getTextBounds(units, 0, units.length(), unitsTextBounds);

int width = (textBounds.width() > unitsTextBounds.width()) ? textBounds.width() : unitsTextBounds.width();

Bitmap bitmap = Bitmap.createBitmap(width + 10, 90,
Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(bitmap);
canvas.drawText(speed, width / 2 + 5, 50, paint);
canvas.drawText(units, width / 2, 90, unitsPaint);

return bitmap;
}

private void getDownloadSpeed() {

long mRxBytesPrevious = TrafficStats.getTotalRxBytes();

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

long mRxBytesCurrent = TrafficStats.getTotalRxBytes();

long mDownloadSpeed = mRxBytesCurrent - mRxBytesPrevious;

float mDownloadSpeedWithDecimals;

if (mDownloadSpeed >= 1000000000) {
mDownloadSpeedWithDecimals = (float) mDownloadSpeed / (float) 1000000000;
mUnits = " GB";
} else if (mDownloadSpeed >= 1000000) {
mDownloadSpeedWithDecimals = (float) mDownloadSpeed / (float) 1000000;
mUnits = " MB";

} else {
mDownloadSpeedWithDecimals = (float) mDownloadSpeed / (float) 1000;
mUnits = " KB";
}


if (!mUnits.equals(" KB") && mDownloadSpeedWithDecimals < 100) {
mDownloadSpeedOutput = String.format(Locale.US, "%.1f", mDownloadSpeedWithDecimals);
} else {
mDownloadSpeedOutput = Integer.toString((int) mDownloadSpeedWithDecimals);
}

}

@Override
public void onDestroy() {
super.onDestroy();
mDestroyed = true;
mNotifyMgr.cancelAll();
}
private void createNotificationChannel() {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel( MyApp.CHANNEL_ID, MyApp.CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
mNotificationManager.createNotificationChannel(channel);
new NotificationCompat.Builder(this, MyApp.CHANNEL_ID);
}
}
}

--

--

--

I’m a good husband, father and Senior Developer.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

MySQLDump ERROR: Duplicate entry for key ‘PRIMARY’.

Convert your text file into CSV using Python

My internship experience as a Software Engineer Intern at 99x

The Future of Low/No Code

My first CLI program written in Ruby

Elegantly craft a 12-factor app in Go

Alexa Integration with Smart Irrigation Controller

Installing applications as Super Hero on Windows

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
CodingwithSaud

CodingwithSaud

I’m a good husband, father and Senior Developer.

More from Medium

App Storage Options

Android deep dive: findViewById

OxygenOS 12 for OnePlus 9 and 9 Pro is rolling out once more, hopefully fixes all the issues…

The Quickest Way to Create an Android QR Code Scanner