Android Mobile Development
Resources
App Lifecycle
  • onCreate()
  • onStart()/onRestart()
  • onResume()
  • onPause()
  • onStop()
  • onDestroy()

See: Android Activity Lifecycle

Activities

Activities are equivalent to forms, and can be call directly by any other activity or app.

findViewById() is a way to locate resources within Activity.

Event Listeners
  • onClick()
  • onFocusChange()
  • onLongClick()
  • onKey()
  • onTouch()

Example 1:

public class MainActivity extends AppCompatActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        Button btnAdd = (Button) findViewById(R.id.btnAdd);
        btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Do something, such as add to values
                EditText txtVal1 = (EditText) findViewById(R.id.txtVal1);
                EditText txtVal2 = (EditText) findViewById(R.id.txtVal2);
 
                int val1 = (int) Integer.parseInt(txtVal1.getText().toString());
                int val2 = (int) Integer.parseInt(txtVal2.getText().toString());
                int result = val1 + val2;
 
                final TextView lblResult = (TextView) findViewById(R.id.lblResult);
                lblResult.SetText(result + "");  // append empty string to convert operation to string
 
                Log.d("MyApp", "We clicked a button!");
                Toast.makeText(this, "We clicked a button!", Toast.LENGTH_SHORT).show();
            }
        });
 
    }
}

Example 2: Sharing onClickListener with multiple buttons in same Activity:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    // Resources
    private TextView txt;
    private Button btn;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        txt = (TextView) findViewById(R.id.txtTest);
        btn = (Button) findViewById(R.id.btnTest);
        btn.setOnClickListener(this);
    }
 
    @Override
    public void onClick(View view) {
        // do something
        switch(view.getId()) {
            case R.id.btnTest:
                Log.d("MyApp", "We clicked a button!");
                txt.SetText("We clicked a button!");
                Toast.makeText(this, "YEs!!", Toast.LENGTH_SHORT).show();
                break;
            // case ...
        }
    }
}
Intents

Call for an activity into action (your own or other apps), which can carry a data payload. Eg: Calling dialer from your app, or calling email client when sending an email, or calling a new activity from within your app.

To deliver an intent:

  • context.startActivity()
  • context.startService()
  • context.sendBroadcast()

To handle an intent:

  • IntentService
  • BroadcastReceiver

Implicit Intent

Intents that do not define which activity will handle the request, but rather seek a registered app to handle the provided data payload.

// Call dialer app to handle phone number
Intent intentDialNumber = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:4071233500"));
if (intentDialNumber.resolveActivity(getPackageManager()) != null) {
    startActivity(intentDialNumber);
}
 
// Call contacts to handle contact selection
Intent intentSelectContact = new Intent(Intent.ACTION_DIAL, new Uri("content://contacts"));
if (intentSelectContact.resolveActivity(getPackageManager()) != null) {
    startActivity(intentSelectContact);
}
 
// Call web browser to handle URL
Intent intentViewWebsite = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.acme.com"));
if (intentViewWebsite.resolveActivity(getPackageManager()) != null) {
    startActivity(intentViewWebsite);
}
 
// Call a mapping app to handle geolocation (lat,long,zoom)
Intent intentShowLocation = new Intent(Intent.ACTION_VIEW, Uri.parse("geo:28.6027902,-81.4232732,14z"));  
if (intentShowLocation.resolveActivity(getPackageManager()) != null) {
    startActivity(intentShowLocation);
}
 
// Display all activities supporting Action View that can handle intent
Intent intentShowAllActivities = new Intent(Intent.ACTION_VIEW);
if (intentShowAllActivities.resolveActivity(getPackageManager()) != null) {
    startActivity(intentShowAllActivities);
}

Explicit Intent

Intents that fully define the required activity that should handle the action and its data payload.

For example, in the MainActivity, you can define an intent:

//...
public class MainActivity extends AppCompatActivity 
{
    @Override
    public void onClick(View view)
    {
        switch(view.getId()) {
            case R.id.btnShowIntent:
                Intent intentDataHandler = new Intent(this, TargetActivity.class);
                intentDataHandler.putExtra("Key1", "Value1");  // data payload (optional)
                intentDataHandler.putExtra("Key2", "Value2");  // data payload (optional)
                intentDataHandler.putExtra("com.acme.myapp.Key3", "Value3");  // use full path with key (recommended)
                intentDataHandler.putExtra("Key4.TEAM_OBJ", aTeamObj); // parcelable object (eg. object of type Team)
                startActivity(intentDataHandler);
                break;
        }
    }
}

In your target activity, retrieve the intent as follows:

//...
public class TargetActivity extends AppCompatActivity 
{
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(saveInstanceState);
        setContentView(R.layout.activity_target);
 
        //-----------------------------------
        // Get data payload (if available)
        //-----------------------------------
        // Method 1
        Bundle bundle = getIntent().getExtras();   
        String str = bundle.getString("Key1");
        Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
 
        // Method 2
        Intent intent = getIntent();
        if (intent.hasExtra("Key2")) {
            str = intent.getExtras().getString("Key2");
            Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
        }
 
        // Method 3
        if (getIntent().hasExtra("Key3")) {
            str = getIntent().getExtras().getString("Key3");
            Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
        }
 
        // Parcelable data
        Team objTeam;
        if (intent.hasExtra("Key4.TEAM_OBJ")) {
            Log.d("MyApp", "Retrieving intent extras...");
            objTeam = intent.getParcelableExtra("Key4.TEAM_OBJ");
            Toast.makeText(this, "Team Name: "+ objTeam.name, Toast.LENGTH_SHORT).show();
        }
    }
}

A parcelable extra must be of a type supporting parcelable. For example:

package com.acme.myapp;
 
import android.os.Parcel;
import android.os.Parcelable;
 
public class Team implements Parcelable
{
    public long id = 0;
    public String name = "";
    public String number = "";
    public int ranking = 0;
 
    // Default constructor
    Team()
    {
 
    }
 
    // In constructor, read variables from Parcel. 
    // Important: Read them in the same sequence in which they were written in Parcel.
    public Team(Parcel in) {
        id = in.readLong();
        name = in.readString();
        number = in.readString();
        ranking = in.readInt();
    }
 
    @Override
    public int describeContents() {
        return 0;
    }
 
    // Write member variables in Parcel. 
    // Write in any order. Not required to write all members in Parcel.
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // Write data in any order
        dest.writeLong(id);
        dest.writeString(name);
        dest.writeString(number);
        dest.writeInt(ranking);
    }
 
    // De-serialize the object
    public static final Parcelable.Creator<Team> CREATOR = new Parcelable.Creator<Team>(){
        public Team createFromParcel(Parcel in) {
            return new Team(in);
        }
 
        public Team[] newArray(int size) {
            return new Team[size];
        }
    };
}

Intent Examples

For example, in the MainActivity, you can define an intent:

//...
public class MainActivity extends AppCompatActivity implements View.OnClickListener
{
    // Resources
    private TextView txtHello;
    private Button btnDialNumber;
    private Button btnViewWebsite;
    //...
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        txtHello = (TextView) findViewById(R.id.txtHello);
        btnDialNumber = (Button) findViewById(R.id.btnDialNumber);
        btnDialNumber.setOnClickListener(this);
        btnViewWebsite= (Button) findViewById(R.id.btnViewWebsite);
        btnViewWebsite.setOnClickListener(this);
        //...
    }
 
    @Override
    public void onClick(View view)
    {
        switch(view.getId()) {
            case R.id.btnDialNumber:
                Intent intentDialNumber = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:4071233500"));
                if (intentDialNumber.resolveActivity(getPackageManager()) != null) {
                    startActivity(intentDialNumber);
                }
                break;
 
            case R.id.btnViewWebsite:
                Intent intentViewWebsite = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.acme.com"));
                if (intentViewWebsite.resolveActivity(getPackageManager()) != null) {
                    startActivity(intentViewWebsite);
                }
                break;
 
            case R.id.btnShowLocation:
                Intent intentShowLocation = new Intent(Intent.ACTION_VIEW, 
                    Uri.parse("geo:28.6027902,-81.4232732,14z"   // lat,long,zoom
                ));
                if (intentShowLocation.resolveActivity(getPackageManager()) != null) {
                    startActivity(intentShowLocation);
                }
                break;
 
            case R.id.btnShowAllActivities: 
                // Display all activities supporting Action View that can handle intent
                Intent intentShowAllActivities = new Intent(Intent.ACTION_VIEW);
                if (intentShowAllActivities.resolveActivity(getPackageManager()) != null) {
                    startActivity(intentShowAllActivities);
                }
                break;
 
            case R.id.btnShowToast:
                Intent intentShowToast = new Intent(MainActivity.this, 
                    SampleActivity.class   // target activity
                );
                if (intentShowToast.resolveActivity(getPackageManager()) != null) {
                    startActivity(intentShowToast);
                }
                break;
 
            case R.id.btnShowSampleActivity:
                Intent intentShowSampleActivity = new Intent("com.acme.myapp.SampleActivity");             
                if (intentShowSampleActivity.resolveActivity(getPackageManager()) != null) {
                    startActivity(intentShowSampleActivity);
                }
                break;
        }
    }
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.acme.myapp.MainActivity">
 
    <Button
        android:id="@+id/btnDialNumber"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="24dp"
        android:text="@string/live"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
    <Button
        android:id="@+id/btnViewWebsite"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="@string/archives"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.501"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnDialNumber" />
 
        <!-- More controls ... -->
 
</android.support.constraint.ConstraintLayout>

In the manifest.xml, you can add intent filters:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.acme.myapp">
 
    <application ...>
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".SampleActivity">
            <intent-filter>
                <!-- Action Name to call directly -->
                <action android:name="com.acme.myapp.SampleActivity" />
                <!-- Action Category.  Required when including an action name -->
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <activity
            android:name=".Sample2Activity">
            <intent-filter>
                <!-- Optional: Action Type by which to respond -->
                <action android:name="android.intent.action.VIEW" />
                <!-- Action Category.  Required when including an action name -->
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>
 
</manifest>
Debugging with logcat
Log.d("MyAppTag", "A debug message");  // standard debug message
Log.e("MyAppTag", "A debug message");  // error message
Log.w("MyAppTag", "A debug message");  // warning message
Log.i("MyAppTag", "A debug message");  // info message
ListView

Resources

Under resources (app > res > values), add string arrays in strings.xml. These will be data bound to a ListView control:

<resources>
  <!-- Other resources... -->
  <string name="app_name">MyApp</string>
 
  <!-- String arrays for ListView -->
  <string-array name="arrProducts">
    <item>Table</item>
    <item>Chair</item>
    <item>Stool</item>
  </string-array>
  <string-array name="arrPrices">
    <item>$1.00</item>
    <item>$1.50</item>
    <item>$1.25</item>
  </string-array>
  <string-array name="arrColors">
    <item>Red</item>
    <item>Blue</item>
    <item>Green</item>
  </string-array>
 
</resources>

Data Binding

In the default onCreate() method, add references to the ListView:

package com.acme.myapp;
 
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
 
public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        // ADD ListView here...
    }
}

Add a ListView with a custom item view using an ItemAdapter. You can choose the type of item view:

TextView layout for item

To use a custom layout based on TextView layout, create ListViewDetail layout:

  • Go to project tree, select app > res > layout. Right-click and select New > Layout resource file.
  • File name: listview_detail
  • Root element: TextView

Activity code:

public class MainActivity extends AppCompatActivity 
{
    // Properties
    ListView lstProducts;
    String[] arrProducts;
    String[] arrPrices;
    String[] arrColors;
 
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        Resources res = getResources();
        lstProducts = (ListView) findViewById(R.id.lstProducts);
        arrProducts = res.getStringArray(R.array.arrProducts);
        arrPrices   = res.getStringArray(R.array.arrPrices);
        arrColors   = res.getStringArray(R.array.arrColors);
 
        // Example: Using layout resource based on TextView
        lstProducts.setAdapter(new ArrayAdapter<String>(
          this,                      // context
          R.layout.listview_detail,  // detail view layout
          arrProducts                // data
        ));
 
    }
}

RelativeLayout/ConstraintLayout layout for item

You will need the following:

Item-Detail Activity (to be used by ItemAdapter)

To use a custom layout based on RelativeLayout or ConstraintLayout, create ListViewDetail layout:

  • Go to project tree, select app > res > layout. Right-click and select New > Layout resource file.
  • File name: listview_detail
  • Root element: RelativeLayout or ConstraintLayout
  • Edit detail form by adding controls (TextView, ImageView, etc.) that can be associated with the different attributes (fields) for the item object represented.

Activity code:

import com.acme.myapp.ItemAdapter;
 
public class MainActivity extends AppCompatActivity 
{
    ListView lstProducts;
    String[] arrProducts;
    String[] arrPrices;
    String[] arrColors;
 
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        Resources res = getResources();
        lstProducts = (ListView) findViewById(R.id.lstProducts);
        arrProducts = res.getStringArray(R.array.arrProducts);
        arrPrices   = res.getStringArray(R.array.arrPrices);
        arrColors   = res.getStringArray(R.array.arrColors);
 
        // Example: Using custom ItemAdapter with custom layout
        ItemAdapter itemAdapter = new ItemAdapter(
            this,                               // context
            arrProducts, arrPrices, arrColors   // data
        );  
        lstProducts.setAdapter(itemAdapter);
 
    }
}

ItemAdapter

Create class ItemAdapter

  • Go to project tree, select app > java > <your app package name>. Right-click and select New > Java Class.
  • Name: ItemAdapter
  • Kind: Class
  • Superclass: android.widget.BaseAdapter
package com.acme.myapp;
 
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
 
public class ItemAdapter extends BaseAdapter
{
    // Properties
    LayoutInflater mInflater;
    String[] arrProducts;
    String[] arrPrices;
    String[] arrColors;
 
    //
    // Constructor: Create custom contructor so properties get assigned right away
    //
    public ItemAdapter(Context cx, String[] prod, String[] prices, String[] colors)
    {
        arrProducts = prod;
        arrPrices = prices;
        arrColors = colors;
 
        mInflater = (LayoutInflater) cx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
 
    @Override
    public int getCount()
    {
        return arrProducts.length;
    }
 
    @Override
    public Object getItem(int idx)
    {
        return arrProducts[idx];
    }
 
    @Override
    public long getItemId(int idx)
    {
        return idx;
    }
 
    @Override
    public View getView(int idx, View view, ViewGroup viewGroup)
    {
        // Use layout inflater.  Use listview_detail.xml layout
 
        View vw = mInflater.inflate(R.layout.listview_detail, null);
        TextView txtProduct = (TextView) vw.findViewById(R.id.txtProduct);
        TextView txtPrice   = (TextView) vw.findViewById(R.id.txtPrice);
        TextView txtColor   = (TextView) vw.findViewById(R.id.txtColor);
 
        String strProduct = arrProducts[idx];
        String strPrice   = arrPrices[idx];
        String strColor   = arrColors[idx];
 
        txtProduct.setText(strProduct);
        txtPrice.setText(strPrice);
        txtColor.setText(strColor);
 
        return vw;
    }
}
ImageView
  • Copy images to app > res > drawable folder in project tree.
  • Create an additional activity to display list item detail (including image)
  • Add controls to display item properties in activity canvas.
    • TextView control for item name and description.
    • ImageView control for item image.

Add an ItemClickListener for the ListView in MainActivity activity. This will launch the secondary activity with the ListView item details:

protected void onCreate(Bundle savedInstanceState) {
    // ...
    lstTeams.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Log.d("RoboticsLeague", "Loading rubric for Team " + (position+1));
            Toast.makeText(getApplicationContext(), "Loading rubric for Team " + (position+1), Toast.LENGTH_SHORT).show();
 
            Intent showRubricActivity = new Intent(getApplicationContext(), RobotRubricActivity.class);
            showRubricActivity.putExtra("com.voirtech.roboticsleague.TEAM_ID", (position+1)+"");
            startActivity(showRubricActivity);
        }
    });
}

On the secondary activity, process the intent:

package com.acme.roboticsleague;
 
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
 
public class RobotRubricActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_robot_rubric);
 
        Intent intent = getIntent();
        String strTeamId = intent.getExtras().getString("com.acme.roboticsleague.TEAM_ID");
        TextView lblTeamId = (TextView) findViewById(R.id.lblTeamId);
        lblTeamId.setText("Team " + strTeamId);
 
        Button btnSaveRubric = (Button) findViewById(R.id.btnSaveRubric);
        btnSaveRubric.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Do something, such as add to values
                SeekBar barDurability           = (SeekBar) findViewById(R.id.barDurability);
                SeekBar barMechanicalEfficiency = (SeekBar) findViewById(R.id.barMechanicalEfficiency);
                SeekBar barMechanization        = (SeekBar) findViewById(R.id.barMechanization);
 
                String valDurability            = (String) (barDurability.getProgress() + "");
                String valMechanicalEfficiency  = (String) (barMechanicalEfficiency.getProgress() + "");
                String valMechanization         = (String) (barMechanization.getProgress() + "");
 
                //final TextView lblResult = (TextView) findViewById(R.id.lblResult);
                //lblResult.SetText(result + "");  // append empty string to convert operation to string
 
                String msg = String.format("Saved evaluation at: %s, %s, %s", valDurability, valMechanicalEfficiency, valMechanization);
                Log.d("RoboticsLeague", msg);
                Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
            }
        });
 
    }
}

Secondary Activity

The secondary activity with item details would look like:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".RobotRubricActivity">
 
    <TextView
        android:id="@+id/lblMechanicalDesign"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="56dp"
        android:text="Mechanical Design"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
    <TextView
        android:id="@+id/lblDurability"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="4dp"
        android:text="Durability"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/lblMechanicalDesign" />
 
    <TextView
        android:id="@+id/lblMechanicalEfficiency"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="12dp"
        android:text="Mechanical Efficiency"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/lblDurability" />
 
    <TextView
        android:id="@+id/lblMechanization"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="12dp"
        android:text="Mechanization"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/lblMechanicalEfficiency" />
 
    <TextView
        android:id="@+id/lblTeamId"
        android:layout_width="85dp"
        android:layout_height="27dp"
        android:layout_marginEnd="268dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Team ID"
        android:textAlignment="viewStart"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
    <SeekBar
        android:id="@+id/barDurability"
        style="@style/Widget.AppCompat.SeekBar.Discrete"
        android:layout_width="156dp"
        android:layout_height="23dp"
        android:layout_marginEnd="16dp"
        android:layout_marginTop="76dp"
        android:max="4"
        android:progress="3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
    <SeekBar
        android:id="@+id/barMechanicalEfficiency"
        style="@style/Widget.AppCompat.SeekBar.Discrete"
        android:layout_width="156dp"
        android:layout_height="23dp"
        android:layout_marginEnd="16dp"
        android:layout_marginTop="8dp"
        android:max="4"
        android:progress="2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/barDurability" />
 
    <SeekBar
        android:id="@+id/barMechanization"
        style="@style/Widget.AppCompat.SeekBar.Discrete"
        android:layout_width="156dp"
        android:layout_height="23dp"
        android:layout_marginEnd="16dp"
        android:layout_marginTop="8dp"
        android:max="4"
        android:progress="3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/barMechanicalEfficiency" />
 
    <Button
        android:id="@+id/btnSaveRubric"
        android:layout_width="87dp"
        android:layout_height="34dp"
        android:layout_marginEnd="8dp"
        android:layout_marginTop="4dp"
        android:text="Save"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
    <TextView
        android:id="@+id/lblRobotDesignRubric"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="4dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Robot Design Rubric"
        android:textSize="18sp"
        app:layout_constraintEnd_toStartOf="@+id/btnSaveRubric"
        app:layout_constraintStart_toEndOf="@+id/lblTeamId"
        app:layout_constraintTop_toTopOf="parent" />
 
</android.support.constraint.ConstraintLayout>
Database Connection