How to build Stock Tracking App in Android Studio


In this video tutorial, an stock tracking app is built in the Android Studio. To fetch the stock prices from NASDAQ, Free trial API IEXCoud.io is used. 

Add dependency for the Volley in build.gradle (App Level)

dependencies {
    implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.11.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
implementation("com.android.volley:volley:1.2.1")
}

Code snippet for mainacivity.java 

package com.epicgamers.stockactivity;

import androidx.appcompat.app.AppCompatActivity;

import android.animation.ObjectAnimator;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

TextView stockPriceTextView, exchangeTextView, companyText;
EditText symbol;
Button updateButton;
String symbolString;
private RequestQueue requestQueue;
double previousPrice = 0.0;
private static final String API_KEY = "pk_******************************"; // API key here
private final Handler handler = new Handler(Looper.getMainLooper());
private Timer timer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
stockPriceTextView = findViewById(R.id.stockPriceTextView);
exchangeTextView = findViewById(R.id.exchangeTextView);
companyText = findViewById(R.id.companyTextView);

updateButton = findViewById(R.id.updateButton);
symbol = findViewById(R.id.symbolName);
requestQueue = Volley.newRequestQueue(this);

updateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
symbolString = symbol.getText().toString();
if(!symbolString.isEmpty())
{
fetchStockPrice();
}
else {
Toast.makeText(MainActivity.this, "Please enter a valid symbol", Toast.LENGTH_SHORT).show();
}
}
});

timer = new Timer();
symbolString = symbol.getText().toString();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
if(!symbolString.isEmpty())
{
fetchStockPrice();
}
}
}, 0, 2*1000);

}

private void fetchStockPrice() {
String symbolString = symbol.getText().toString();
String apiUrl = "https://cloud.iexapis.com/stable/stock/" + symbolString + "/quote?token=" +API_KEY;
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, apiUrl, null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
String stockPrice = response.getString("latestPrice");
String exchange = response.getString("primaryExchange");
String company = response.getString("companyName");

double stockPriceValue = Double.parseDouble(stockPrice);
updateStockPrice(stockPriceValue, "Exchange: " + exchange, "Company: " + company);

} catch (JSONException e) {
e.printStackTrace();
Log.e("ERROR", "Error parsing JSON: " + e.getMessage());
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
if(error.networkResponse!=null&& error.networkResponse.data!=null)
{
String responeBody = new String(error.networkResponse.data);
Log.e("API_ERROR", "Error Response: " + responeBody);
}
Log.e("API_ERROR", "Error fetching stock price: " + error.getMessage());
}
});
requestQueue.add(request);

}

private void updateStockPrice(double currentPrice, String exchange, String company) {
double instantaneousChange = currentPrice - previousPrice;
previousPrice = currentPrice;
handler.post(new Runnable() {
@Override
public void run() {
startBlinkAnimation(stockPriceTextView);
String formattedPrice = String.format("%2f", currentPrice);
stockPriceTextView.setText(formattedPrice);
int textColor = (instantaneousChange>=0.00) ? Color.GREEN : Color.RED;
stockPriceTextView.setTextColor(textColor);
exchangeTextView.setText(exchange);
companyText.setText(company);
}
});

}


private void startBlinkAnimation(final TextView textView)
{
ObjectAnimator blink = ObjectAnimator.ofFloat(textView, "alpha", 1f, 0f, 1f);
blink.setDuration(200);
blink.start();
}

@Override
protected void onDestroy() {
super.onDestroy();
if(timer!=null)
{
timer.cancel();
timer.purge();
}
}
}
 

Code Snippet for activity_main.xml is as below

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity"
android:orientation="vertical"
android:padding="15dp"
android:background="#0d2a50">

<EditText
android:id="@+id/symbolName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter Stock Symbol"
android:textColor="@color/white"
android:layout_marginTop="200dp"
android:textSize="18sp"
android:textColorHint="#818181"
android:inputType="textCapCharacters"/>

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

<TextView
android:id="@+id/stockPriceText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="Stock Price: "
android:textColor="@color/white"
android:textSize="24sp"
android:textStyle="bold"/>

<TextView
android:id="@+id/stockPriceTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text=""
android:textColor="@color/white"
android:textSize="24sp"
android:textStyle="bold"/>

</LinearLayout>

<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="#2d4a70"
android:elevation="5dp">

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">

<TextView
android:id="@+id/exchangeTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="Exchange: "
android:textColor="@color/white"
android:textSize="20sp"
android:textStyle="bold"/>

<TextView
android:id="@+id/companyTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="Company: "
android:textColor="@color/white"
android:textSize="20sp"
android:textStyle="bold"/>

</LinearLayout>

</androidx.cardview.widget.CardView>

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/updateButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Get Latest Price"
android:layout_marginTop="20sp"
android:background="#ee6c4d"
android:textColor="@color/white"
android:textAllCaps="false"
android:textSize="24sp"/>

</LinearLayout>

Code Snippet for AndroidManifest.XML

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Stockactivity"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

The output will look like this




That's all folks  ✋



Comments