This tutorial will take you through a step-by-step process on how to create a simple currency converter app in Android studio.
We shall put all our Simple Currency Converter source code in activity_main.xml and the Java implementations in MainActivity.java.
Features of Currency Converter:
- Live Currency Exchange Rates
- Currency Exchange Rate Conversion
- Supported All Most Popular Country’s Currency.
- Uses of API and Firebase
- Good UI Design
MainActivity.java:
public class MainActivity extends AppCompatActivity {
TextView usdTxt, inrTxt;
Button check;
Spinner spin1,spin2;
private EditText mPasswordField;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
spin1 = findViewById(R.id.spinner1);
spin2 = findViewById(R.id.spinner2);
check = findViewById(R.id.check_btn);
mPasswordField = findViewById(R.id.password_field);
check.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String s =spin1.getSelectedItem().toString();
String[] split = s.split("-");
String firstSubString = split[0];
String secondSubString = split[1];
Common.str1 = firstSubString;
String s2 =spin2.getSelectedItem().toString();
String[] split2 = s2.split("-");
String firstSubString2 = split2[0];
Common.str2 = firstSubString2;
if (Common.str1.equals(Common.str2))
{
Toast.makeText(MainActivity.this, "Please select different Conversion", Toast.LENGTH_SHORT).show();
}
else {
if (getInputText() == null || getInputText().equals(""))
{
Toast.makeText(MainActivity.this, "Enter some amount", Toast.LENGTH_SHORT).show();
}
else {
Common.amt = Double.parseDouble(getInputText());
startActivity(new Intent(MainActivity.this, ConversionActivity.class));
mPasswordField.setText("");
}
}
}
});
}
public String getInputText() {
return mPasswordField.getText().toString();
}
}
activity_java.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
app:title="Currency Conversion " />
android:textStyle="bold">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:text="From Currency"
android:textColor="@color/black"
android:textSize="18sp" />
<Spinner
android:background="@color/Green_Apple"
android:id="@+id/spinner1"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_margin="7dp"
android:layout_weight="1"
android:entries="@array/from_array"
tools:ignore="MissingConstraints" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:text="To Currency"
android:textColor="@color/black"
android:textSize="18sp" />
<Spinner
android:background="@color/Green_Apple"
android:id="@+id/spinner2"
android:layout_width="match_parent"
android:layout_margin="7dp"
android:layout_weight="1"
android:layout_height="50dp"
android:entries="@array/to_array"
tools:ignore="MissingConstraints" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Enter Amount :"
android:layout_gravity="center_vertical"
android:textColor="@color/black"
android:textSize="28sp"
android:textStyle="bold" />
<EditText
android:id="@+id/password_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:gravity="center"
android:inputType="number"
android:textColor="@color/black"
android:minHeight="48dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="@+id/check_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="11dp"
android:text="Check"
/>
</LinearLayout>
</RelativeLayout>
activity_conversion.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".ConversionActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="11dp"
android:textSize="22sp"
android:text="Amount From : "/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="11dp"
android:layout_marginRight="11dp"
android:id="@+id/amt_from"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="Rate : "
android:layout_marginRight="11dp"
android:id="@+id/rate"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="11dp"
android:textSize="22sp"
android:text="Amount To : "/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="11dp"
android:layout_marginRight="11dp"
android:id="@+id/amt_to"/>
<ProgressBar
android:visibility="gone"
android:layout_width="25dp"
android:id="@+id/pro1"
android:layout_height="25dp"
android:layout_margin="11dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_alignParentRight="true" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Take a picture go Invoice to save it"/>
<ImageView
android:clickable="true"
android:scaleType="fitXY"
android:id="@+id/imgView"
android:layout_margin="11dp"
android:layout_width="match_parent"
android:layout_height="200dp"/>
</RelativeLayout>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"
android:id="@+id/progress"/>
<Button
android:id="@+id/save_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="11dp"
android:text="Save this"
/>
<Button
android:id="@+id/json_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="11dp"
android:text="show JSON"
/>
</LinearLayout>
</RelativeLayout>
Now,in the following the main conversion activity is done using the giver API which will convert all our amount in the given country currency.it will show in the following:
ConversionActivity.java:
public class ConversionActivity extends AppCompatActivity {
EditText fromTxt, toTxt;
Button home;
TextView rte;
ProgressBar pro1, progressBar;
Button js;
FirebaseFirestore firebaseFirestore;
String sinr, susd;
ImageView imageView;
private static final int CAMERA_CODE2 = 22;
private Uri postUri = null;
String sjon = "";
private StorageReference storageRef;
String obj1,obj2;
private static String URL = "";
String downloadUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_conversion);
firebaseFirestore = FirebaseFirestore.getInstance();
storageRef = FirebaseStorage.getInstance().getReference();
fromTxt = findViewById(R.id.amt_from);
toTxt = findViewById(R.id.amt_to);
js = findViewById(R.id.json_btn);
home = findViewById(R.id.save_btn);
progressBar = findViewById(R.id.progress);
URL = "https://api.exchangeratesapi.io/latest?symbols="+Common.str1+","+Common.str2;
pro1 = findViewById(R.id.pro1);
rte = findViewById(R.id.rate);
imageView = findViewById(R.id.imgView);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
selectPic();
}
});
home.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addData();
}
});
pro1.setVisibility(View.VISIBLE);
fetch();
fromTxt.setText("" + Common.str1 + " " + Common.amt);
js.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(ConversionActivity.this, ""+sjon, Toast.LENGTH_SHORT).show();
}
});
}
private void addData() {
if (postUri != null) {
final int randomS = new Random().nextInt(610000) + 20000;
final int gh = randomS;
progressBar.setVisibility(View.VISIBLE);
home.setVisibility(View.GONE);
final StorageReference filePath = storageRef.child("post_images").child(gh + ".jpg");
filePath.putFile(postUri).continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
@Override
public Task<Uri> then(@NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
if (!task.isSuccessful()) {
throw task.getException();
}
return filePath.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
@Override
public void onComplete(@NonNull Task<Uri> task) {
if (task.isSuccessful()) {
Uri downUri = task.getResult();
downloadUri = String.valueOf(downUri);
Map<String,Object> vm = new HashMap<>();
vm.put("sfrom",obj2);
vm.put("sto",obj1);
vm.put("imgUrl",downloadUri);
firebaseFirestore.collection("Internship").document().set(vm).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Toast.makeText(ConversionActivity.this, "added", Toast.LENGTH_SHORT).show();
}
});
}
}
});
}
}
private void selectPic() {
if (ContextCompat.checkSelfPermission(ConversionActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
CropImage.activity()
.setGuidelines(CropImageView.Guidelines.ON)
.setMinCropResultSize(512, 512)
.start(ConversionActivity.this);
} else {
reqPermissioner();
}
}
private void fetch() {
StringRequest stringRequest = new StringRequest(Request.Method.GET, URL,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
//converting the string to json array object
// JSONObject jsonResponse;
JSONObject emp = (new JSONObject(response)).getJSONObject("rates");
sjon = String.valueOf(emp);
double x = Double.parseDouble(emp.getString(Common.str1));
double y = Double.parseDouble(emp.getString(Common.str2));
double main = y / x * Common.amt;
toTxt.setText("" + Common.str2 + " " + main);
pro1.setVisibility(View.GONE);
obj1 = toTxt.getText().toString();
obj2 = fromTxt.getText().toString();
rte.setText("Rate : " + x + " * " + y);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
//adding our stringrequest to queue
Volley.newRequestQueue(this).add(stringRequest);
}
private void reqPermissioner() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(this)
.setTitle("Storage Permission")
.setMessage("Storage permission is needed to select image..")
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(ConversionActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, CAMERA_CODE2);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).create().show();
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, CAMERA_CODE2);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == CAMERA_CODE2) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Toast.makeText(this, "Granted..", Toast.LENGTH_SHORT).show();
selectPic();
} else {
// Toast.makeText(this, "Denied", Toast.LENGTH_SHORT).show();
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
CropImage.ActivityResult result = CropImage.getActivityResult(data);
if (resultCode == RESULT_OK) {
postUri = result.getUri();
Glide.with(this).load(postUri).into(imageView);
// Toast.makeText(this, "Photo selected", Toast.LENGTH_SHORT).show();
} else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
Exception error = result.getError();
Toast.makeText(this, "Photo not selected properly", Toast.LENGTH_SHORT).show();
}
}
}
}
Final Words for Currency Converter App
That is all folks! I hope you enjoyed this tutorial. If you get stuck somewhere, let us know in the comments section below. We will try to help you as soon as possible. Note that there are many ways to develop your currency converter and this is just one of them.