Pass information between activities - java

I am doing a project where I have to program a pedometer. The pedometer will work using a button and you have to tell the length of your steps. I made a main activity that let you choose between go anonymous an another one that let you register. The aplication works when I register or when I go anonymous, and the step length is passed well to the third activity, an activity where you can press a button and increase the number of steps done and the meters done. In this activity there is another button to configure the length of your steps and I want to pass all the info to the anonymous activity to change only the length of the steps and I pass all the info. I used the method putExtra() and getIntent().getExtra().getString(), but only works going to the main activity to the registe/anonymous activity and then going to the pedometer activity, but when i want to configure the length of the steps the aplications stops.
This is my code for the anonymous activity:
if(this.getIntent().hasExtra("name")){
names=this.getIntent().getExtras().getString("name");
}else{
names="";
}
if(this.getIntent().hasExtra("user")){
userName=this.getIntent().getExtras().getString("user");
}else{
userName="";
}
if(this.getIntent().hasExtra("pass")){
password=this.getIntent().getExtras().getString("pass");
}else{
password="";
}
if(this.getIntent().hasExtra("feetBefore")){
footBefore=this.getIntent().getExtras().getString("feetBefore");
}else{
footBefore="0";
}
if(this.getIntent().hasExtra("steps")){
stepsDone=this.getIntent().getExtras().getString("steps");
}else{
stepsDone="0";
}
Button continueBtn = findViewById(R.id.continueAnonymous);
foot = findViewById(R.id.lengthFeetAnonymous);
continueBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String footSize = String.valueOf(foot.getText());
if(!footSize.equals("")) {
Intent mainAnonymous = new Intent(getApplicationContext(), Main5Activity.class);
mainAnonymous.putExtra("name", names);
mainAnonymous.putExtra("user", userName);
mainAnonymous.putExtra("pass", password);
mainAnonymous.putExtra("feet", footSize);
mainAnonymous.putExtra("steps", stepsDone);
mainAnonymous.putExtra("feetBefore", footBefore);
startActivity(mainAnonymous);
finish() ;
}else{
Toast.makeText(Main4Activity.this, "You have to complete all the backets.",
Toast.LENGTH_SHORT).show();
}
}
});
This is the code of my pedometer activity:
Bundle parameters = this.getIntent().getExtras();
if(parameters != null){
name = parameters.getString("name");
username = parameters.getString("user");
password = parameters.getString("pass");
String foot = parameters.getString("feet");
String footBefore = parameters.getString("feetBefore");
String stepsDone = parameters.getString("steps");
if(stepsDone!=null) cont = Integer.parseInt(stepsDone);
else cont =0;
if(footBefore!=null)feetBefore = Integer.parseInt(footBefore);
else feetBefore =0;
if(foot !=null)feet = Float.parseFloat(foot)/100;
else feet = (float) 0.43;
cont2 = cont*feetBefore;
}else {
name = "";
username = "";
password = "";
feet = (float) 0.43;
}
increase = findViewById(R.id.increaseStep);
configuration = findViewById(R.id.confBtn);
saveMain = findViewById(R.id.saveBtnMain);
resume = findViewById(R.id.resumBtn);
final TextView steps = findViewById(R.id.stepCounter);
final TextView km = findViewById(R.id.kilometerCounter);
steps.setText(String.format(Locale.ENGLISH,"%d Steps",cont));
String aux =String.format(Locale.ENGLISH,"%.2f Meters", cont2);
km.setText(aux);
increase.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
cont++;
steps.setText(String.format(Locale.ENGLISH,"%d Steps",cont));
cont2 += feet;
String aux =String.format(Locale.ENGLISH,"%.2f Meters", cont2);
km.setText(aux);
}
});
configuration.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent conf = new Intent(getApplicationContext(), Main4Activity.class);
conf.putExtra("name", name);
conf.putExtra("user", username);
conf.putExtra("pass", password);
String aux2 = String.valueOf(cont);
conf.putExtra("steps", aux2);
float aux4 =feet*100;
String aux3 = String.valueOf(aux4);
conf.putExtra("feetBefore", aux3);
startActivity(conf);
finish() ;
}
});
}
I started to learn android yesterday so I don't know what I am doing wrong. If you can help me I would apreciate it. In addition, I think it's something about the bundle.

Add all data in a bundle and check only if bundle!=null –by Milan Pansuriya
I don't know the difference between using a bundle to pass al the data and putExtra to my intent but this works for me. Thank you Milan Pansuriya.

Related

NumberFormatException For Input String "4018.B"

The following code comes from a Android App for Handheld Scanner Device; the Device should scan different Barcodes and QR codes, different digit ranges, numbers and digits;
that´s why I decided to go with .matcher instead of Regular Expressions; The following code works fine when it comes to parse combinations like "1367+700" etc.:
editBarcode.setOnClickListener(new View.OnClickListener() { //tv is the TextView.
public void onClick(View v) {
code = editBarcode.getText().toString();
XXXStorageApp.getInstance().setScannedCode(code);
editBarcode.setText("");
if (ScanService.checkEnteredCode(code, basic, content, MainDetailActivity.this) == true) {
return;
}
else {
Pattern p = Pattern.compile(code);
Matcher matcher = p.matcher(Pattern.quote("\\+"));
if (matcher.find()){
retrievedItemNo = String.valueOf(matcher);
}
String intermediateItemNo = code;
String[] splitString = intermediateItemNo.split(Pattern.quote("+"));
retrievedItemNo = splitString [0];
String intermediateString = code.substring(code.indexOf("+") + 1);
retrievedQuantity = intermediateString.split("\\+")[0];
if(XXXStorageApp.getInstance().NoList.contains(retrievedItemNo) || XXXStorageApp.getInstance().EanList.contains(scannedCode)){
Log.d(String.valueOf(XXXStorageApp.getInstance().NoList),"NoList");
Log.d(String.valueOf(XXXStorageApp.getInstance().EanList),"EanList");
}
else {
Log.d(String.valueOf(XXXStorageApp.getInstance().NoList),"NoList");
Log.d(String.valueOf(XXXStorageApp.getInstance().EanList),"EanList");
Vibrator vibrator;
vibrator = (Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(3000);
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
Toast.makeText(getApplicationContext(), R.string.not_in_database, Toast.LENGTH_LONG).show();
return;
}
if (!addBooking.isEnabled() == true && removeBooking.isEnabled())
{
AddBookingMessage message = new AddBookingMessage();
message.setType("add-item-to-pallet");
message.setPalNo(receivedPalNo);
message.setItem(retrievedItemNo);
if (String.valueOf(retrievedQuantity).matches("") ||
retrievedQuantity == null ||
retrievedQuantity.trim().isEmpty()) {
final Dialog dialog = new Dialog(MainDetailActivity.this, 0);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(true);
dialog.setContentView(R.layout.sortiment_layout);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
TextView textView = dialog.findViewById(R.id.textView4);
Button okButton = dialog.findViewById(R.id.ok);
okButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
retrievedQuantity = textView.getText().toString();
message.setQuantity(Integer.valueOf(retrievedQuantity));
message.setSource(source);
message.setTime(time);
RestClient.putBookingOnPallet(basic, message, MainDetailActivity.this);
dialog.dismiss();
}
});
Button cancelButton = dialog.findViewById(R.id.cancel);
cancelButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
}
else
{
message.setQuantity(Integer.valueOf(retrievedQuantity));
message.setSource(source);
message.setTime(time);
RestClient.putBookingOnPallet(basic, message, MainDetailActivity.this);
}
}
if (addBooking.isEnabled() && !removeBooking.isEnabled() == true)
{
AddBookingMessage message = new AddBookingMessage();
message.setType("remove-item-from-pallet");
message.setPalNo(receivedPalNo);
message.setItem(retrievedItemNo);
message.setEan(scannedCode);
if (spinner != null && spinner.getSelectedItem() != null) {
source = spinner.getSelectedItem().toString();
}
if (String.valueOf(retrievedQuantity).matches("") || retrievedQuantity == null
|| retrievedQuantity.trim().isEmpty())
{
final Dialog enterDialog = new Dialog(MainDetailActivity.this, 0);
enterDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
enterDialog.setCancelable(true);
enterDialog.setContentView(R.layout.sortiment_layout);
enterDialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
TextView enterQuantityView = enterDialog.findViewById(R.id.textView4);
Button okQuantityButton = enterDialog.findViewById(R.id.ok);
okQuantityButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
retrievedQuantity = enterQuantityView.getText().toString();
message.setQuantity(Integer.valueOf(retrievedQuantity));
message.setSource(source);
message.setTime(time);
RestClient.removeItemFromPallet(basic, message, MainDetailActivity.this);
enterDialog.dismiss();
}
});
Button cancelQuantityButton = enterDialog.findViewById(R.id.cancel);
cancelQuantityButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
enterDialog.dismiss();
}
});
enterDialog.show();
}
else {
message.setQuantity(Integer.valueOf(retrievedQuantity));
message.setSource(source);
message.setTime(time);
RestClient.removeItemFromPallet(basic, message, MainDetailActivity.this);
}
}
editBarcode.setText("");
}}
however the App crashes with a
java.lang.NumberFormatException: For input string: "4018.B"
So, the problem here is to parse a string like "4018.B+95".
I don´t know how to handle this mixed input String with .matcher and definitely don´t want to use a Regular Expression; so basically, all of the following Input Strings - including Type conversion - should be handled correctly:
1256+70
1235.B+70
1256+70+DB
1235.B+70+DB
1256+70+DB2020-123
1235.B+70+DB2020-123
1256+0+DB2020-123
1235.B+0+DB2020-123
So, basically I need a condition for .matcher() that handles input like
"1235.B"
a mixed Integer and String; I need to store it in one variable which is of type String;
the problem here is that the "." in "1235.B" is not recognized and the App crashes hence, because the Number contains a string (".B")
So, two questions here:
How can I use .matcher() to recognize if a String contains ".B" or ".C" or anything similar?
How do I handle the different Types correctly in one Variable type?
As I am stuck with this, I would appreciate any hints or help.

getIntent(), getStringExtra() are deprecated

I'm trying to pass strings from one activity to another.
googleMap.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
String m = markerMap.get(marker.getId());
for(int i = 0; i < 8; i++) {
if(m.equals(name[i])) {
Intent intent = new Intent(MapsActivity.this, CustomInfoWindowAdapter.class);
intent.putExtra("FOOD_BANK",name[i]);
intent.putExtra("STREET_ADDRESS",address[i]);
intent.putExtra("WEBSITE",website[i]);
startActivity(intent);
}
}
}
});
That's the chunk of code that is supposed to send the strings to the other activity.
private void rendowWindowText(Marker marker, View view) {
Intent intent = getIntent();
String foodBank = getStringExtra("FOOD_BANK");
TextView tvTitle = (TextView) view.findViewById(R.id.title);
tvTitle.setText(foodBank);
String snippet = marker.getSnippet();
TextView tvSnippet = (TextView) view.findViewById(R.id.snippet);
String address = getStringExtra("STREET_ADDRESS");
tvSnippet.setText(address);
/*if(!title.equals("")) {
tvTitle.setText(title);
}*/
}
This bit is what should be receiving the data but getIntent() and getStringExtra() are deprecated. I've tried surpressing the deprecation with #SuppressWarnings("deprecation") before the method. I've tried restarting Android Studio and my computer with no avail. I've tried getActivity().getIntent(); and no luck either.
The message when I hover my cursor over the deprecated getIntent() is:
Cannot resolve method 'getIntent' in 'CustomInfoWindowAdapter'
Would really appreciate any ideas on how to fix this because I'm very new to Android Studio and Java in general.
To get the data which u sent, use the following code :
Bundle extras = getIntent().getExtras();
if (extras != null) {
String foodBank = extras.getString("FOOD_BANK");
String address = extras.getString("STREET_ADDRESS");
}

Failed to pass value from one activity from another (only null value passed)

I tried to pass variable from one activity to another. In the main activity I managed to call back the values using Toast message.
MainActivity.java
search = (Button) findViewById(R.id.search);
search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View w) {
subreg = spinner_subregion.getSelectedItem().toString();
reg = spinner_region.getSelectedItem().toString();
pettype = spinner_pet.getSelectedItem().toString();
petnumber = spinner_num.getSelectedItem().toString();
Intent intent = new Intent(MainActivity, Result.class);
intent.putExtra("subregion", subreg);
intent.putExtra("region", reg);
intent.putExtra("petnum", petnumber);
intent.putExtra("pet", pettype);
startActivity(intent);
}
}
However, when I passed the value to Result.java, it only returns null. I tried searching for solutions and still does not work for me. Anyone knows how can I pass the data?
Result.java
Bundle extras = getIntent().getExtras();
if (extras!=null){
subreg = extras.getString("subreg");
reg = extras.getString("reg");
pettype = extras.getString("pettype");
petnumber = extras.getString("petnumber");
}
Try this
MainActivity.java
Intent myIntent = new Intent(this, NewActivity.class);
intent.putExtra("subregion", subreg);
intent.putExtra("region", reg);
intent.putExtra("petnum", petnumber);
intent.putExtra("pet", pettype);
startActivity(myIntent)
Result.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view);
Intent intent = getIntent();
if(intent ==null){
........
.......
}else{
String subregion= intent.getStringExtra("subregion");
String region= intent.getStringExtra("region");
String petnum= intent.getStringExtra("petnum");
String pet= intent.getStringExtra("pet");
}
}
This is my code after changing it.
MainActivity.java
search = (Button) findViewById(R.id.search);
search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View w) {
subreg = spinner_subregion.getSelectedItem().toString();
reg = spinner_region.getSelectedItem().toString();
pettype = spinner_pet.getSelectedItem().toString();
petnumber = spinner_num.getSelectedItem().toString();
Intent intent = new Intent(Pet_sitting.this, Pet_sitting_result.class);
intent.putExtra("subreg", subreg);
intent.putExtra("reg", reg);
intent.putExtra("pettype", pettype);
intent.putExtra("petnumber", petnumber);
startActivity(intent);
}
});
Result.java
Intent intent = getIntent();
if (intent == null){
Toast.makeText(getApplicationContext(),"Null value passed",Toast.LENGTH_SHORT).show();
}
else{
subreg= intent.getStringExtra("subreg");
reg= intent.getStringExtra("reg");
pettype = intent.getStringExtra("pettype");
petnumber = intent.getStringExtra("petnumber");
Toast.makeText(getApplicationContext(),subreg + " " + reg + " " + pettype + " " + petnumber,Toast.LENGTH_SHORT).show();
}
As i can see you are using a Spinner in your code.
So it's Obvious a spinner can give you only one value at a time after Spinning the wheel...
you need to set the Code inside in null value Exception...
like...if it's null don't pass empty value inside intent
maybe it's worked...if it's then reply
MainActivity.java
if(subreg != null){
reg = spinner_region.getSelectedItem().toString();
intent.putExtra("reg", reg);
}
startActivity(intent);
Rsult.java
Intent intent = getIntent();
if (intent == null){
Toast.makeText(getApplicationContext(),"Null value passed",Toast.LENGTH_SHORT).show();
}else{
reg= intent.getStringExtra("reg");
Toast.makeText(getApplicationContext(),reg.toString,Toast.LENGTH_SHORT).show();
}

How to get data from Intent or SharedPreferences

I'm writing a weather app in Android Studio and I've a problem. When the user closes the app, I want to save the last city searched, and I used SharedPreferences for this.
If the user wants to search a new city, I have a "search button" that starts a new activity, where the user can choose another city and with an Intent put the string in the MainActivity.
The problem is to check (at the start of the app) if a SharedPreferences exists(and get old data from this) or intent is != null (and get new data from this).
This is my code in "OnCreate" method. It works on emulator but not on my smartphone:
value = ""; //this is a String
pref = getSharedPreferences("meteo", Context.MODE_PRIVATE);
receive_from_intent = getIntent(); //This intent gets from "SearchActivity".
add_city.setOnClickListener(new View.OnClickListener() { //this is the search button
#Override
public void onClick(View view) {
Intent start_new = new Intent(MainActivity.this, SearchActivity.class);
MainActivity.this.startActivity(start_new);
}
});
if (receive_from_intent.getExtras() != null) {
value = receive_from_intent.getStringExtra("luogo"); //if it's a string you stored.
//luogo means "city"
if (!value.matches("")) {
SharedPreferences.Editor editor = pref.edit();
editor.putString("luogo", value);
editor.apply();
}
url = "https://api.openweathermap.org/data/2.5/weather?q=" + value + ",it&mode=json&lang=it&units=metric&APPID=e8cff7ac36757b1ea60b460f036140df";
url2 = "https://api.openweathermap.org/data/2.5/forecast?q=" + value + ",it&mode=json&lang=it&units=metric&APPID=e8cff7ac36757b1ea60b460f036140df";
CercaLuogo(url, url2);
} else if (pref.contains("luogo")) {
value = pref.getString("luogo", "");
url = "https://api.openweathermap.org/data/2.5/weather?q=" + value + ",it&mode=json&lang=it&units=metric&APPID=e8cff7ac36757b1ea60b460f036140df";
url2 = "https://api.openweathermap.org/data/2.5/forecast?q=" + value + ",it&mode=json&lang=it&units=metric&APPID=e8cff7ac36757b1ea60b460f036140df";
CercaLuogo(url, url2);
} else Toast.makeText(this, "Click on search button and insert new city.", Toast.LENGTH_SHORT).show();

How to pass data in a class to another member?

I have this code and I am trying to pass this.thecost to the public void click() method but it looks like it is not working because I receive "Paymnet Failed" when click the paypal button.
What did i go wrong?
by the way, what do you call the private {}, private void {} - all those function() looking thing?
private void initUI(int theprice) {
launchPayPalButton = mPayPal.getCheckoutButton(this,
PayPal.BUTTON_278x43, CheckoutButton.TEXT_PAY);
LinearLayout.LayoutParams params = new
LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.bottomMargin = theprice;
this.thecost = theprice;
launchPayPalButton.setLayoutParams(params);
launchPayPalButton.setOnClickListener(this);
((LinearLayout)findViewById(R.id.main_layout2)).addView(launchPayPalButton);
}
public void onClick(View v) {
payWithPaypal(this.thecost);
}
private void payWithPaypal(Integer gg) {
PayPalPayment newPayment = new PayPalPayment();
BigDecimal bigDecimal=new BigDecimal(gg);
newPayment.setSubtotal(bigDecimal);
newPayment.setCurrencyType(Currency.getInstance(Locale.US));
newPayment.setRecipient("email#hotmail.com");
newPayment.setMerchantName("My Merchant");
Intent paypalIntent = PayPal.getInstance().checkout(newPayment, this);
this.startActivityForResult(paypalIntent, 1);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(resultCode) {
case Activity.RESULT_OK:
String payKey = data.getStringExtra(PayPalActivity.EXTRA_PAY_KEY);
data.getStringExtra(PayPalActivity.EXTRA_PAY_KEY);
Toast.makeText(this,"Paymnet Successful",Toast.LENGTH_LONG).show();
break;
case Activity.RESULT_CANCELED:
Toast.makeText(this,"Paymnet Cancel",Toast.LENGTH_LONG).show();
break;
case PayPalActivity.RESULT_FAILURE:
Toast.makeText(this,"Paymnet Failed",Toast.LENGTH_LONG).show();
String errorID =
data.getStringExtra(PayPalActivity.EXTRA_ERROR_ID);
String errorMessage =
data.getStringExtra(PayPalActivity.EXTRA_ERROR_MESSAGE);
break;
}
EDITED: I call initUI() at the oncreate method
EDITED AGAIN: I change the global variable to 'double' because the price usually have decimal place.
Now i tried to toast the value and i see the error much clearer. The toast display a message that the value that was passed is "0.0". And because of that, there is an error of 'Payment Failed' and invalid payment.
int eprice;
double thecost;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detail);
//Data mSource = new Data;
Intent myLocalIntent = getIntent();
Bundle myBundle = myLocalIntent.getExtras();
eprice = myBundle.getInt("eprice");
String epricetxt = myBundle.getString("eprice");
Adapter mAdapter = new Adapter(this, mSource);
//details = (Data) mAdapter.getItem(pos);
TextView theprice = (TextView) findViewById(R.id.priceTxt);
theprice.setText("Price: $" + epricetxt);
this.setCost(eprice);
this.thecost = eprice;
//Paypal
mPayPal=PayPal.initWithAppID(this,Constants.PAYPAL_APP_ID,PayPal.ENV_SANDBOX);
initUI(eprice);
}
private void initUI(int theprice) {
launchPayPalButton = mPayPal.getCheckoutButton(this,
PayPal.BUTTON_278x43, CheckoutButton.TEXT_PAY);
LinearLayout.LayoutParams params = new
LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.bottomMargin = theprice;
this.thecost = theprice;
launchPayPalButton.setLayoutParams(params);
launchPayPalButton.setOnClickListener(this);
((LinearLayout)findViewById(R.id.main_layout2)).addView(launchPayPalButton);
}
public void onClick(View v) {
//
payWithPaypal(getCost());
}
public void setCost(int cost) {
this.thecost = cost;
}
public double getCost() {
return this.thecost;
}
private void payWithPaypal(Double gg) {
PayPalPayment newPayment = new PayPalPayment();
Toast.makeText(getApplicationContext(),gg.toString(), Toast.LENGTH_LONG).show();
BigDecimal bigDecimal=new BigDecimal(gg);
newPayment.setSubtotal(bigDecimal);
newPayment.setCurrencyType(Currency.getInstance(Locale.US));
newPayment.setRecipient("email#hotmail.com");
newPayment.setMerchantName("My Merchant");
Intent paypalIntent = PayPal.getInstance().checkout(newPayment, this);
this.startActivityForResult(paypalIntent, 1);
}
We don't have enough information to tell you what went wrong here. For some reason, the PayPal API returned a failure status code. Maybe you don't have an internet connection?
Check the value of the error message string that you retrieved in this line:
String errorMessage = data.getStringExtra(PayPalActivity.EXTRA_ERROR_MESSAGE);
You can use the debugger to inspect it, or use the Log.e function in the Logger class to log it to Logcat so you can read it.
As for your second question:
by the way, what do you call the private {}, private void {} - all those function() looking thing?
In Java, those "function looking things" are called Methods.
EDIT: Okay, now that you've showed us your onCreate method, I can see where you are getting the value that you eventually pass to onInit here:
eprice = myBundle.getInt("eprice");
Doing this implies that you saved the value previously in the bundle in onSaveInstanceState(Bundle)
Did you do that? How does it get the value when you are starting the Activity for the first time?
Using my most updated code, I have no idea why my eprice doesn't work. But I have alternative solution. All i need to do is change
initUI(eprice);
initUI(Double.valueOf(epricetxt));

Categories

Resources