Android App ep.102

My Network Reporter v.2

For this project we are going to be recreating the network reporter application in Kotlin to look at the advantages and uniqueness Kotlin can provide.

Previous application utilizing java: Android App ep.101

Application Purpose:

This will remain the same as the last application….

We want to discern if transmitting a file of a size A across a network with a speed B gives us a reasonable time in seconds.

Our size of the file size is measured in MiB and our network speed is measured in Mbps.

We know that 1 B = 8 b; 1 MiB = 220 B; 1 Mbps = 106 bps.

Video to view in action: https://youtu.be/JUkxk5NhutM

activity_main.xml  Layout


This will remain the same as well since we just want to look at the benefits of Kotlin to Java.

Screen Shot 2018-10-15 at 8.44.27 AM

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/textView"
        android:layout_width="96dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:paddingHorizontal="10dp"
        android:text="@string/file_size_label"
        android:textAlignment="center"
        android:textAllCaps="false"
        android:textSize="14sp" />

    <EditText
        android:id="@+id/fileSizeInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/file_input_hint"
        android:inputType="number" />

</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/networkSpeedLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/network_label"
        android:textAlignment="center"
        android:textSize="14sp" />

    <EditText
        android:id="@+id/networkSpeedInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/network_hint"
        android:inputType="number" />
</LinearLayout>

<TextView
    android:id="@+id/resultDisplay"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Input is needed for both File Size and Network Speed to estimate time"
    android:textAlignment="center"
    android:textColor="@android:color/black"
    android:textSize="18sp" />

On our Kotlin side…


package com.amsuarez.mynetworkreporter

import android.app.Activity
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.widget.EditText
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    fun EditText.changed() {
       this.addTextChangedListener(object: TextWatcher {
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
            override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
                if (fileSizeInput.text.toString() == "" || networkSpeedInput.text.toString() == "") {
                    resultDisplay.text = "Input is needed for both File Size and Network Speed to estimate time"
                } else {
                    val myb = Integer.parseInt(fileSizeInput.text.toString()).toDouble() * Math.pow(2.0, 20.0) * 8.0
                    val mybps = Integer.parseInt(networkSpeedInput.text.toString()) * Math.pow(10.0, 6.0)
                    resultDisplay.setText(String.format("%.1f", myb / mybps) + " seconds")
                }
            }
            override fun afterTextChanged(s: Editable) {}
        })
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        fileSizeInput.changed()
        networkSpeedInput.changed()
    }
}

Here we utilized some really cool features that Kotlin provides us with.

Extension Functions:

We utilized these to extend upon the EditText class to allow us to run a text watcher object in any EditText. This gives us a very clean call in our onCreate fun increasing readability.

Where are the findViewByIds? 👀

Kotlin provides a feature that allows us to reference straight out of our activities.

It is done by importing:

 import kotlinx.android.synthetic.main.activity_main.*

This allows us to no longer need to call findViewById and instead we can reference directly into our activities.

Objects? 🤔

Here we use object as an anonymous class that inherits TextWatcher allowing us to override the TextWatcher without having to “formally declare a new class”.

For more on Objects: https://kotlinlang.org/docs/reference/object-declarations.html

 

Android App ep.101

 

My Network Reporter

For this project we are going to be creating a simple application using TextFields, EditText, and a TextWatcher.

This tutorial assumes you know basic information about widgets and Java programming

Application Purpose:

We want to discern if transmitting a file of a size A across a network with a speed B gives us a reasonable time in seconds.

Our size of the file size is measured in MiB and our network speed is measured in Mbps.

We know that 1 B = 8 b; 1 MiB = 220 B; 1 Mbps = 106 bps.

Video to view in action: https://youtu.be/JUkxk5NhutM

activity_main.xml  Layout


Screen Shot 2018-10-15 at 8.44.27 AM.png

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/textView"
        android:layout_width="96dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:paddingHorizontal="10dp"
        android:text="@string/file_size_label"
        android:textAlignment="center"
        android:textAllCaps="false"
        android:textSize="14sp" />

    <EditText
        android:id="@+id/fileSizeInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/file_input_hint"
        android:inputType="number" />

</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/networkSpeedLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/network_label"
        android:textAlignment="center"
        android:textSize="14sp" />

    <EditText
        android:id="@+id/networkSpeedInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/network_hint"
        android:inputType="number" />
</LinearLayout>

<TextView
    android:id="@+id/resultDisplay"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Input is needed for both File Size and Network Speed to estimate time"
    android:textAlignment="center"
    android:textColor="@android:color/black"
    android:textSize="18sp" />

Here we kept it as simple as possible using two linear layouts to block each input and label and a separate TextView to display a result.

 

On our Java side…


public class MainActivity extends AppCompatActivity {
    EditText fileSize;
    EditText networkSpeed;
    TextView result;

     // Here we use a TextWatcher to see if there are any changes.
    TextWatcher watchChange = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            if(fileSize.getText().toString().equals("") || networkSpeed.getText().toString().equals("")){
                result.setText("Input is needed for both File Size and Network Speed to estimate time");
            }
            else {
               // this section calculates the time to send.
                Double myb = Integer.parseInt(fileSize.getText().toString()) * Math.pow(2, 20) * 8;
                Double mybps = Integer.parseInt(networkSpeed.getText().toString()) * Math.pow(10, 6);
                result.setText(String.format("%.1f", myb / mybps) + " seconds");
            }
        }
        @Override
        public void afterTextChanged(Editable editable) {}
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

         // this section assigns our java code to the xml android widgets
        fileSize        = (EditText) findViewById(R.id.fileSizeInput);
        networkSpeed    = (EditText) findViewById(R.id.networkSpeedInput);
        result          = (TextView) findViewById(R.id.resultDisplay);
        
        //this assigns the TextWatcher to both entry fields
        fileSize.addTextChangedListener(watchChange);
        networkSpeed.addTextChangedListener(watchChange);
    }
}

For more on TextWatchers visit Android documentation here : https://developer.android.com/reference/android/text/TextWatcher

Medium: Article: https://medium.com/@austinmsuarez/android-app-ep-101-83e0f0af8aa0