This is an old revision of the document!


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 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)
                startActivity();
                break;
        }
    }
}

In your target activity, retrieve the intent as follows:

//...
public class ActivityTargetSample extends AppCompatActivity 
{
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(saveInstanceState);
        setContentView(R.layout.activity_target_sample);
 
        Bundle bundle = getIntent().getExtras();   // get data payload (if available)
        String str = bundle.getString("Key1");
 
        Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
 
        // Better yet
        if (getIntent().hasExtra("Key2")) {
            str = getIntent().getExtras().getString("Key2");
            Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
 
        }
    }
}

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"));
                startActivity(intentDialNumber);
                break;
 
            case R.id.btnViewWebsite:
                Intent intentViewWebsite = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.acme.com"));
                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
                ));  
                startActivity(intentShowLocation);
                break;
 
            case R.id.btnShowAllActivities: 
                // Display all activities supporting Action View that can handle intent
                Intent intentShowAllActivities = new Intent(Intent.ACTION_VIEW);
                startActivity(intentShowAllActivities);
                break;
 
            case R.id.btnShowToast:
                Intent intentShowToast = new Intent(MainActivity.this, 
                    SampleActivity.class   // target activity
                );
                startActivity(intentShowToast);
                break;
 
            case R.id.btnShowSampleActivity:
                Intent intentShowSampleActivity = new Intent("com.acme.myapp.SampleActivity");             
                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

DB Connector

Download the appropriate Java database connector:

  • Download JDBC / ConnectorJ library (select 'Platform Independent' version).
  • Extract JAR file to some folder.
  • Add JAR file as module: app, right-click then New > Module, then select 'Import .JAR/.AAR Package', and find JAR file.
  • JAR package should be now listed under the project Gradle Scripts: build.gradle (mysql-connector-java-8.0.11).
  • If there is an error including the JAR package, try the following:
    • In settings.gradle (Project Settings), add references to the mysql-connector-java:
      include ':app'
      include ':mysql-connector-java-8.0.11'
  • Sync project (File > Sync Project with Gradle Files).
  • Add mysql-connector-java module as dependency to app module:
    • Right-click on the app module folder, and select “Open Module Settings” (F4).
    • In the top left navigation pane of the “Project Structure” window, go to category “Modules” and select tab “Dependencies”.
    • Click on the green plus (+), and select 'Module Dependencies'. Select the mysql-connector-java module.
    • Click OK, and close all the opened windows. A synchronization process should take place once more.
  • If there is an error including the JAR package, try the following:
    • In build.gradle (Module:app), add references to compile mysql-connector-java under dependencies:
      dependencies {
        //...
        compile project(':mysql-connector-java-8.0.11')
      }
  • If succesful, under the app module folder there should be a mysql-connector-java module folder.
  • Include the classes required in your code.

Manifest

Add permission to access the Internet. Go to app > manifests > AndroidManifest.xml:

<manifest...>
    <uses-permission android:name="android.permission.INTERNET"/>
 
    <application...>
    </application>
</manifest>

Database Strings

Create a class to hold the database strings: File DbStrings.java:

package com.acme.myapp;
 
public class DbStrings
{
  static final String DATABASE_URL  = "192.168.0.1:3306";
  static final String DATABASE_NAME = "mydatabase";
  static final String USERNAME      = "dbuser";
  static final String PASSWORD      = "dbsecret";
}

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
import android.view.ViewGroup;
import android.widget.BaseAdapter;
 
public class ItemAdapter extends BaseAdapter
{
    LayoutInflater mInflater;
    Map<String, Double> map;  // products & prices
 
    List<String> products;
    List<String> prices;
 
    public ItemAdapter(Context cx, Map m)
    {
        map = m;
        products = new ArrayList<String>(map.keySet());
        prices   = new ArrayList<String>(map.keySet());
 
        mInflater = (LayoutInflater) cx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
 
    @Override
    public int getCount()
    {
        return map.size();
    }
 
    @Override
    public Object getItem(int idx)
    {
        return products.get(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 lblProduct = (TextView) vw.findViewById(R.id.lblProduct);
        TextView lblPrice   = (TextView) vw.findViewById(R.id.lblPrice);
 
        String strProduct = arrProducts.get(idx);
        String strPrice   = "$" + arrPrices.get(idx).toString();
 
        lblProduct.setText(strProduct);
        lblPrice.setText(strPrice);
 
        return vw;
    }
}

MainActivity

package com.acme.myapp;
 
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
 
public class MainActivity extends AppCompatActivity 
{
    // Properties
    ItemAdapter itemAdapter;
    Context thisContext;
    ListView lstProducts;
    TextView lblProgress;
    Map<String, Double> mapProducts = new LinkedHashMap<String, Double>();
 
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        Resources res = getResources();
        lstItems      = (ListView) findViewById(R.id.lstItems);
        lblProgress   = (TextView) findViewById(R.id.lblProgress);
        thisContext   = this;
 
        lblProgress.setText("");
 
        Button bntConnect = (Button) findViewById(R.id.btnConnect);
        btnConnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View vw) {
                GetData retrieveData = new GetDate();
                retrieveData.execute("");
            }
        });
    } 
 
    private class GetData extends AsyncTask<String,String,String> 
    {
      // Properties
      String msg = "";   // progress textview
 
      // JDBC driver name and database URL
      static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
 
      // Example: 192.168.0.2:3306
      static final String DB_URL = "jdbc:mysql://"+
          DbStrings.DATABASE_URL + "/" +
          DbStrings.DATABASE_NAME;
 
       @Override
       protected void onPreExecute() 
       {
           lblProgress.setText("Connecting to database...");
       }
 
       @Override
       protected String doInBackground(String... params) 
       {
           Connection conn = null;
           Statement stmt = null;
 
           try {
               Class.forName(JDBC_DRIVER);
               conn = DriverManager.getConnection(DB_URL, DbStrings.USERNAME, DbStrings.PASSWORD);
               stmt = conn.createStatement();
               String sql = "SELECT * FROM products";
               ResultSet rs = stmt.executeQuery(sql);
               while(rs.next()) {
                   String name = rs.getString("name");
                   double price = rs.getDouble("price");
 
                   mapProducts.put(name, price);
               }
 
               msg = "Process complete.";
 
               rs.close();
               stmt.close();
               conn.close();
 
           } catch (SSQLException connError) {
              msg = "Exception was thrown for JDBC.";
              connError.printStackTrace();
           } catch (ClassNotFoundException ex) {
              msg = "A 'Class not Found' exception was thrown.";
              ex.printStackTrace();
           } finally {
               try {
                   if (stmt != null) { stmt.close(); }
               } catch (SQLException ex) {
                   stmt.close();
               }
               try {
                   if (conn != null) { conn.close(); }
               } catch (SQLException ex) {
                   conn.close();
               }
           }
           return null;
       }
 
       @Override
       protected void onPostExecute(String msg) {
           lblProgress.setText(this.msg);
           if (mapProducts.size() > 0) {
               itemAdapter = new ItemAdapter(thisContext, mapProducts);
               lstProducts.setAdapter(itemAdapter());
           }
       }
    }
}
References