I have an app that uses several activities. One activity is to manually enter some values and I have four buttons in that activity. When one of the buttons is clicked it starts a new activity to get the input.
The problem is that the layout for the activity is not displayed when the get_input() function of this activity is run. It should get a decimal value from an EditText. but I keep getting a runtime error of "Invalid Float """.
If I comment out the get_input() function then the layout for the activity is shown fine.
Here is the xml file :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/manually_entry" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Please enter the decimal Latitude"
android:singleLine="true"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Negative is South"
android:singleLine="true"
/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:inputType="numberDecimal|numberSigned"
android:id="#+id/enter_decimal_number" />
</LinearLayout>
And here is the calling activity :
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lat_long_manual_entry);
}
// manual entry dialog buttons
public void enter_lat_dec_deg(View v) {
Intent intent = new Intent(this.getApplicationContext(), ManuallyEnterNumbers.class);
startActivity(intent);
}
And here is the called activity that requests the actual input from the user :
package com.example.david.gpstest;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
/**
* Created by david on 06/03/16.
*/
public class ManuallyEnterNumbers extends Activity {
private EditText input;
private float decimal_input;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.manually_enter_numbers);
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onResume() {
super.onResume();
get_input();
}
public void get_input() {
input = (EditText) findViewById(R.id.enter_decimal_number);
input.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
decimal_input = Float.valueOf(input.getText().toString());
return true;
}
return false;
}
});
}
}
I am showing the function get_input() in the onStart() method but IO have also tried it in the onResume() method and that does not work either.
Any help here would be very much appreciated.
Thank You.
Float.valueOf(input.getText().toString());
The common mistake here newbies ofter make is lack of string sanitization prior attempting conversion. Even , (comma) instead of . (dot) entered as decimal part separator will cause exception to be thrown. So you simply must make string convertable (i.e. by checking what's inside, replacing , with . etc) not to mention you should expect exception to come and use try/catch to catch it to avoid app crash you are facing now.
David, hello, this is yourself. Basically you can forget about sanitizing the input. Because you have android:inputType="numberDecimal|numberSigned" in your xml you will get a numeric keypad with the comma, and space disabled. So all that the user can enter is digits a decimal point and a minus sign. Exactly what you want. Secondly, you can forget about the onStart() and onResume() methods and stick everything in onCreate() and then it will work. Your xml is absolutely fine. Your calling activity absolutely fine too although it would be a good idea to use an intent.putExtra() and an intent.getExtra() to pass the decimal_input value back to the calling activity. I have posted the code for the calling activity and the called activity below to help you out a bit.
public class ManualEntry extends Activity {
// private View layout;
// private PopupWindow enter_manual_dec_deg;
// LayoutInflater inflater;
// private EditText input;
// private float decimal_input;
// private String result;
static final int REQUEST_CODE = 1;
String button_pressed;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lat_long_manual_entry);
}
#Override
protected void onResume() {
super.onResume();
}
// manual entry dialog buttons
public void enter_lat_dec_deg(View v) {
Intent intent = new Intent(this.getApplicationContext(), ManuallyEnterNumbers.class);
button_pressed = "lat_dec_deg";
intent.putExtra("Button pressed", button_pressed);
startActivityForResult(intent, REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE) {
if (resultCode == RESULT_OK) {
double result = data.getDoubleExtra("returnData", 0.0d);
if (result < -180 || result > 180) {
Toast.makeText(this, "Value outside range - Range is -180 to 180", Toast.LENGTH_LONG).show();
}
else {
DecimalFormat var = new DecimalFormat("###.########");
Toast.makeText(this, var.format(result), Toast.LENGTH_LONG).show();
disable_button(button_pressed);
}
}
}
}
void disable_button(String pressed_button) {
Button dec_deg_button = (Button) findViewById(R.id.button_lat_dec_deg);
Button d_m_s_button = (Button) findViewById(R.id.button_lat_deg_min_sec);
if (pressed_button != null) {
if (pressed_button == "lat_dec_deg" || button_pressed == "lat_d_m_s") {
dec_deg_button.setEnabled(false);
d_m_s_button.setEnabled(false);
}
}
}
}
/*
public void enter_lat_d_m_s (View v) {
}
public void enter_lon_dec_deg(View v) {
}
public void enter_lon_d_m_s(View v) {
}
*/
And the called activity
package com.example.david.gpstest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
/**
* Created by david on 06/03/16.
*/
public class ManuallyEnterNumbers extends Activity {
private EditText input;
private String inValue;
private double decimal_input;
private Bundle extras;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.manually_enter_numbers);
extras = getIntent().getExtras();
if (extras != null) {
String buttonPressed = extras.getString("Button pressed");
if (buttonPressed.contentEquals(buttonPressed) ) {
((TextView) findViewById(R.id.enter_decimal_number)).setHint("Decimal degrees of Latitude");
TextView title_text = (TextView) findViewById(R.id.manual_entry_hint);
title_text.setText("Please enter the decimal Latitude");
TextView hint_text = (TextView) findViewById(R.id.manual_entry_hint);
hint_text.setText("(Negative is South)");
}
}
get_input();
}
#Override
protected void onStart() {
super.onStart();
// get_input();
}
#Override
protected void onResume() {
super.onResume();
// get_input();
}
public void get_input() {
input = (EditText) findViewById(R.id.enter_decimal_number);
input.setOnEditorActionListener(new TextView.OnEditorActionListener(){
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
// do stuff here
inValue = input.getText().toString();
if (inValue.isEmpty()) {
Toast.makeText(getApplicationContext(), "Enter a value", Toast.LENGTH_SHORT).show();
}
else {
// some input
decimal_input = Double.parseDouble(inValue);
Intent returnIntent = getIntent();
returnIntent.putExtra("returnData", decimal_input);
setResult(RESULT_OK, returnIntent);
finish();
}
}
return true;
}
});
/*
Intent returnIntent = getIntent();
returnIntent.putExtra("returnData", decimal_input);
setResult(RESULT_OK, returnIntent);
finish();
*/
}
}
I hope that this helps you out a bit.
David.
Related
I am new to Android and programming as a whole and I need a little help with callbacks. I understand the gist of callbacks but I am unsure of how to go about implementing.
Context: I am writing a simple notetaking app that allows the user to write text and saving it to the app. The user can then request to read the file with a button. The text is then displayed on a textview in the main activity. There is an option to wipe this file and this is done with a confirmation pop up, which is another activity. This pop up contains 2 buttons, one to cancel and one to wipe. If the file is not empty it will wipe and does nothing if empty. I am not sure if this is the best way to implement it but I want to use the wipe button to callback to the main activity to clear the textview. The way I was thinking of was by using the callback to send a boolean value back. The main activity will check if the boolean is true and clear the textview if it is. I am unsure of how to implement the callback in my popup display to send this boolean value back to the main activity.
Code for main activity
public class MainActivity extends AppCompatActivity implements Popout.ClearTextView {
Button bnRead,bnWrite,bnClear;
TextView tvFileOP;
EditText etInput;
// private static final String INPUT_CONTENT = "inputContent";
public static final String TV_CONTENT = "textViewContent";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bnRead = (Button) findViewById(R.id.bnRead);
bnWrite = (Button) findViewById(R.id.bnWrite);
bnClear = (Button) findViewById(R.id.bnClear);
tvFileOP = (TextView) findViewById(R.id.tvFileOP);
etInput = (EditText) findViewById(R.id.etInput);
tvFileOP.setMovementMethod(new ScrollingMovementMethod());
final String fileName = "test_file";
String data;
bnRead.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
FileInputStream fIn = openFileInput(fileName);
int c;
String temp = "";
while ( (c=fIn.read()) != -1){
temp = temp + Character.toString((char) c);
}
tvFileOP.setText(temp);
Toast.makeText(getBaseContext(),"file successfully read", Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
});
bnWrite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String data = etInput.getText().toString();
try {
FileOutputStream fOut = openFileOutput(fileName,MODE_APPEND);
fOut.write(data.getBytes());
fOut.close();
etInput.setText("");
Toast.makeText(getBaseContext(),"file successfully written", Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
});
bnClear.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,Popout.class));
}
});
}
#Override
protected void onSaveInstanceState(#NonNull Bundle outState) {
outState.putString(TV_CONTENT,tvFileOP.getText().toString());
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(#NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
tvFileOP.setText(savedInstanceState.getString(TV_CONTENT));
}
#Override
public void clearTextView(Boolean clear) {
if (clear){
tvFileOP.setText("");
}
}
}
Code for popup confirmation menu
public class Popout extends AppCompatActivity {
Button bnClosepopup,bnWipe;
TextView tvConfirmation;
String fileName = "test_file";
TextView tvFileOP;
public interface ClearTextView {
public void clearTextView(Boolean clear);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.popupwindow);
bnClosepopup = (Button) findViewById(R.id.bnClosepopup);
bnWipe = (Button) findViewById(R.id.bnWipe);
tvConfirmation = (TextView) findViewById(R.id.tvConfirmation);
//HIDING THE TOOL BAR AT THE TOP OF THE SCREEN
this.getSupportActionBar().hide();
//GETTING THE SIZE OF THE SCREEN
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
int width = displayMetrics.widthPixels;
getWindow().setLayout((int) (width*0.8) , (int) (0.8*height));
bnClosepopup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
bnWipe.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
File dir = getFilesDir();
File file = new File(dir, fileName);
boolean deleted = file.delete();
Toast.makeText(getBaseContext(),"file has been deleted",Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
finish();
}
});
}
}
I am very new to android development and any tips on how to improve my code would be greatly appreciated :)
In this case there is no way to pass the interface to the other activity, because this is an activity to activity communication.
You have to use some other method, there is multiple ways to approach, the best way I can think of is to use startActivityForResult() to start the activity and then wait for a response to come back, and then query this response in the MainActivity by overriding the onActivityResult() method:
Example
In the MainActivity:
//on click of this button
bnClear.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,Popout.class);
int requestCode = 12; //it could be whatever you want
startActivityForResult(intent , requestCode);
}
});
//override this method
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//this is triggered when you finish the Popout Activity
if(requestCode == 12 && resultCode == Activity.RESULT_OK){
// get the boolean data returned from the Popout Activity
boolean deleted = data.getBooleanExtra("deleted_state" , false); //false is default if no value exists
}
}
In the Popout activity:
bnWipe.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
File dir = getFilesDir();
File file = new File(dir, fileName);
boolean deleted = file.delete();
//send the result to onActivtyResult() in MainActivity
Intent result = new Intent();
result.putExtra("deleted_state", deleted );
setResult(Activity.RESULT_OK, result);
Toast.makeText(getBaseContext(),"file has been deleted",Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
finish();
}
});
UPDATE:
It will be like this:
// get the boolean data returned from the Popout Activity
boolean deleted = data.getBooleanExtra("deleted_state" , false);
if (deleted){
tvFileOP.setText("");
}
..........
As far as what if Understood your problem correctly: You want to control your 'Wipe' button click event from your activity. Here is the solution which may help you.
1: Make an overridden constructor of your dialog class.
2: Create one abstract method in the dialog class. (say - onWipeButtonClick)
You need to make your dialog class abstract as well.
3: Inside on Click Listener of 'Wipe' button, call onWipeButtonClick abstract method.
4: Create the instance of dialog in the main activity where ever you want. The compiler will give you an error because you haven't implemented the call back method.
do implement your onWipeButtonClick method and do needful for wipe data inside the method.
public abstract class WipeDialog extends Dialog{
private Context context;
public WipeDialog(Context context){
this.context = context;
}
public abstract void onWipeButtonClick(boolean isTextEmpty);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.<XML_FILE>);
<initialization>
btnWipe.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onWipeButtonClick(<YOUR_BOOLEAN_CHECK>);
}
});
}
}
And now in Activity:
WipeDialog dialog = new WipeDialog(MainActivity.this) {
#Override
public void onWipeButtonClick(boolean isTextEmpty) {
//Do Need full with respected to your requirement on click of button 'WIPE'
}
};
Hope this will help.
Thanks!
I am writing an Android app to fetch the latest email from a folder and play it using TTS. I want to be able to use it whilst driving so it has to be mostly automatic. Everything so far is working fine until I attempt to capture when the TextToSpeech has finished speaking so we can move on to the next email.
Here is the complete MainActivity.java file:
package uk.co.letsdelight.emailreader;
import android.os.AsyncTask;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.UtteranceProgressListener;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.util.Properties;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.MimeBodyPart;
public class MainActivity extends AppCompatActivity implements TextToSpeech.OnInitListener {
public TextToSpeech tts;
private Bundle ttsParam = new Bundle();
public UtteranceProgressListener utListener;
private boolean isPlaying = false;
private Properties imap = new Properties();
private String textToSpeak = "";
#Override
public void onInit(int ttsStatus) {
if (ttsStatus == TextToSpeech.SUCCESS) {
utListener = new UtteranceProgressListener() {
#Override
public void onStart(String s) {
TextView status = findViewById(R.id.status);
status.setText("started reading (Listener)");
}
#Override
public void onDone(String s) {
Toast.makeText(getApplicationContext(), "Done Event Listener", Toast.LENGTH_LONG).show();
TextView status = findViewById(R.id.status);
status.setText("finished reading (Listener)");
/*ImageButton i = findViewById(R.id.playButton);
i.setImageResource(R.drawable.button_play);*/
isPlaying = false;
}
#Override
public void onStop(String s, boolean b) {
Toast.makeText(getApplicationContext(), "Stop Event Listener", Toast.LENGTH_LONG).show();
TextView status = findViewById(R.id.status);
status.setText("stopped reading (Listener)");
/*ImageButton i = findViewById(R.id.playButton);
i.setImageResource(R.drawable.button_play);*/
isPlaying = false;
}
#Override
public void onError(String s) {
Toast.makeText(getApplicationContext(), "Error Event Listener", Toast.LENGTH_LONG).show();
TextView status = findViewById(R.id.status);
status.setText("Error reading email");
ImageButton i = findViewById(R.id.playButton);
i.setImageResource(R.drawable.button_play);
isPlaying = false;
}
};
tts.setOnUtteranceProgressListener(utListener);
TextView status = findViewById(R.id.status);
status.setText("initialised");
} else {
TextView status = findViewById(R.id.status);
status.setText("failed to initialise");
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
imap.setProperty("mail.store.protocol", "imap");
imap.setProperty("mail.imaps.port", "143");
tts = new TextToSpeech(this,this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void restartPressed(View v) {
if (isPlaying) {
tts.stop();
speak();
}
}
public void playPressed(View v) {
ImageButton i = (ImageButton) v;
if (isPlaying) {
isPlaying = false;
i.setImageResource(R.drawable.button_play);
TextView status = findViewById(R.id.status);
status.setText("");
if (tts != null) {
tts.stop();
}
} else {
isPlaying = true;
i.setImageResource(R.drawable.button_stop);
new Reader().execute();
}
}
class Reader extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
TextView status = findViewById(R.id.status);
status.setText("fetching email");
}
#Override
protected String doInBackground(String... params) {
String toRead = "nothing to fetch";
try {
Session session = Session.getDefaultInstance(imap, null);
Store store = session.getStore();
store.connect(getText(R.string.hostname).toString(), getText(R.string.username).toString(), getText(R.string.password).toString());
Folder inbox = store.getFolder("INBOX.Articles.listen");
if (inbox.exists() && inbox.getMessageCount() > 0) {
inbox.open(Folder.READ_ONLY);
Message msg = inbox.getMessage(inbox.getMessageCount() - 6);
if (msg.getContentType().contains("multipart")) {
Multipart multiPart = (Multipart) msg.getContent();
MimeBodyPart part = (MimeBodyPart) multiPart.getBodyPart(multiPart.getCount() - 1);
toRead = part.getContent().toString();
} else {
toRead = msg.getContent().toString();
}
} else {
toRead = "The folder is empty or doesn't exist";
}
} catch (Throwable ex) {
toRead = "Error fetching email - " + ex.toString();
}
return toRead;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
String body;
TextView status = findViewById(R.id.status);
status.setText("");
try {
Document doc = Jsoup.parse(s);
body = doc.body().text();
} catch (Throwable ex) {
body = "Error parsing email - " + ex.toString();
}
status.setText("email successfully fetched");
textToSpeak = body;
if (isPlaying) {
speak();
}
}
}
private void speak() {
int maxLength = TextToSpeech.getMaxSpeechInputLength();
if (textToSpeak.length() > maxLength) {
textToSpeak = "The email text is too long! The maximum length is " + maxLength + " characters";
}
ttsParam.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "EmailReader");
tts.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, ttsParam, "EmailReader");
}
#Override
protected void onDestroy() {
if (tts != null) {
tts.stop();
tts.shutdown();
}
super.onDestroy();
}
}
The inner class Reader works fine. doInBackground fetches the email and onPostExec strips out any HTML to leave the actual text content of the email. This is passed to the speak() method which does the actual speaking and works.
The issue is with the onUtteranceProgressListener.
Sometimes the onStart(String s) method is called, sometimes it isn't! It seems to never be called the first time the email read out. Mostly it is called for subsequent calls to speak() but not always. About 1 in 5 times it fails to get called. If the listener is called the status displays 'started reading (Listener)' otherwise it shows 'email successfully fetched'.
onDone, onError and onStop are never called.
I have tried using different utteranceID and Bundle values in the tts.speak() call but this makes to difference.
When the app is started, the first status display is 'initialised' which means that the onUtteranceListener must have been set within the onInit method. The TextToSpeech object is instantiated within the activity's onCreate method.
I have looked through all the information I can find which has mostly suggested getting the utteranceID correct. What else can I try in order to get a better understanding of this problem please?
The problem is that the onDone() method (and in fact any of the progress callbacks) is run on a background thread, and therefore the Toast is not going to work, and any code that accesses your UI such as setText(...) may or may not work.
So... the methods probably are being called, but you just can't see that.
The solution to this would be to surround the code in your callbacks with runOnUiThread() like this:
#Override
public void onDone(String s) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Done Event Listener", Toast.LENGTH_LONG).show();
TextView status = findViewById(R.id.status);
status.setText("finished reading (Listener)");
/*ImageButton i = findViewById(R.id.playButton);
i.setImageResource(R.drawable.button_play);*/
isPlaying = false;
}
});
}
Note: It's probably best to initialize your TextView in onCreate() along with everything else instead of in the progress callbacks.
Also, the purpose of the utteranceID is to give each call to speak() a unique identifier that is then passed back to you as the "String s" argument in the progress callbacks.
It's a good idea to give each call to speak a new ("most recent") ID using some kind of random number generator, and then checking it in the progress callbacks.
You can see a similar question and answer regarding this here.
Side note:
Since you have a "restart" button, you should know that on APIs <23, calls to TextToSpeech.stop() will cause the onDone() in your progress listener to be called. On APIs 23+, it calls onStop() instead.
First, make sure you actually have a problem and not a race between who sets the text in what order. Use log statements to make sure it is not actually called.
Try setting queueMode to QUEUE_ADD like:
tts.speak(textToSpeak, TextToSpeech.QUEUE_ADD, ttsParam, "EmailReader");
maybe subsequent calls are cancelling the listener's events from previous texts inputs, as QUEUE_FLUSH suggests.
Also the bundle isn't really needed there, you can set it to null.
Hope any of these helps.
I have this onClickListener method on my login activity in my android app:
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(txtEmail.getWindowToken(), 0);
imm.hideSoftInputFromWindow(txtPassword.getWindowToken(), 0);
String password = txtPassword.getText().toString();
String email = txtEmail.getText().toString();
if ((txtEmail.length() == 0) || (txtPassword.length() == 0)) {
Toast.makeText(LoginMember.this, "You need to provide values for Email and Password", Toast.LENGTH_SHORT).show();
return;
}
//Go ahead and perform the transaction
String[] params = {email,password};
new EndpointsAsyncTaskInsert(LoginMember.this).execute(params);
}
});
It sends data to Google App Engine without any problems, already my EndpointsAsyncTask class defined, etc etc
Now, my problem is, I need to also go to another activity after this, I'm not realyl sure, but If I remember well I could do this automatically when logged in by using SQLite, don't know how to accomplish it here.
Already have the activities I need declared on manifest.
It should be something like this:
#Override
public void onClick(View v){
Intent intent = new Intent(LoginMember.this, WelcomeScreen.class);
startActivity(intent);
}
My problem is that I don't know how to "add" or "append" this activity transaction into this logic, I'm fairly new to android and google app engine, Any ideas???
Thanks in advance!
EDIT
This is my EndpointsAsyncTaskInsert code:
package com.kkoci.shairlook;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;
import com.appspot.shairlook1.userEndpoint.UserEndpoint;
import com.appspot.shairlook1.userEndpoint.model.User;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.extensions.android.json.AndroidJsonFactory;
import com.google.api.client.googleapis.services.AbstractGoogleClientRequest;
import com.google.api.client.googleapis.services.GoogleClientRequestInitializer;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
/**
* Created by kristian on 04/07/2015.
*/
public class EndpointsAsyncTaskInsert extends AsyncTask<String, Void, User> implements GoogleClientRequestInitializer {
private static UserEndpoint myApiService = null;
private Context context;
EndpointsAsyncTaskInsert(Context context) {
this.context = context;
}
#Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
// put it here no in MyClass
abstractGoogleClientRequest.setDisableGZipContent(true);
}
// class MyClass{} // you don't need it
#Override
protected User doInBackground(String... params) {
User response = null;
if (myApiService == null) { // Only do this once
UserEndpoint.Builder builder = new UserEndpoint.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("https://shairlook1.appspot.com/_ah/api/")
.setGoogleClientRequestInitializer(this);
// end options for devappserver
myApiService = builder.build();
}
try {
User users = new User();
users.setEmail(params[0]);
users.setPassword(params[1]);
users.setName(params[2]);
response = myApiService.insertUser(users).execute();
} catch (Exception e) {
Log.d("Could not Add User", e.getMessage(), e);
}
return response;
}
}
SECOND EDIT
This is how it looks right now, it's giving me 'java.lang.NoClassDefFoundError' on this line: new EndpointsAsyncTaskInsert(LoginMember.this) {
:
public class LoginMember extends Activity {
private static
//DbAdapter dbAdapter = null;
//EditText txtUserName;
EditText txtPassword;
EditText txtEmail;
Button btnLogin;
TextView Forgot_text;
Button twitter;
Button facebook;
//Button btnRegister;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
txtPassword = (EditText) findViewById(R.id.et_pw);
txtEmail = (EditText) findViewById(R.id.et_email);
btnLogin = (Button) findViewById(R.id.btn_login);
twitter = (Button) findViewById(R.id.twitter);
facebook = (Button) findViewById(R.id.facebook);
Forgot_text = (TextView) findViewById(R.id.Forgot_text);
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(txtEmail.getWindowToken(), 0);
imm.hideSoftInputFromWindow(txtPassword.getWindowToken(), 0);
String password = txtPassword.getText().toString();
String email = txtEmail.getText().toString();
if ((txtEmail.length() == 0) || (txtPassword.length() == 0)) {
Toast.makeText(LoginMember.this, "You need to provide values for Email and Password", Toast.LENGTH_SHORT).show();
return;
}
//Go ahead and perform the transaction
String[] params = {email,password};
//new EndpointsAsyncTaskInsert(LoginMember.this).execute(params);
/**try{ Intent k = new Intent(LoginMember.this, WelcomeScreen.class);
startActivity(k);
}catch(Exception e){
}**/
new EndpointsAsyncTaskInsert(LoginMember.this) {
protected void onPostExecute(User result) {
super.onPostExecute(result);
// Do something with result
Intent intent = new Intent(LoginMember.this, WelcomeScreen.class);
startActivity(intent);
}
}.execute(params);
}
});
}
public void getUser(View v) {
new EndpointsAsyncTask(this).execute();
}
public void insertUser(View v) {
new EndpointsAsyncTaskInsert(this).execute();
}
}
ok, i see, maybe you should do this, i haven't tryied this yet, but could help you:
Before onCreate method, declare a var of this way:
Activity currentActivity;
then inside onCreate method do this:
currentActivity=this;
so then, when you make you Asyctask, make this:
new EndpointsAsyncTaskInsert(currentActivity.getApplicationContext()).execute(params);
Hope that helps, let's me know if was helpFull, if not i try to help you in another way.
Regards.
In EndpointsAsyncTask class there should be method named onPostExecute() which is executed when your async task is completed. This is the place where you should notify your activity to go to another activity.
There are numerous way to do that.
You can create an Interface class for instance
public interface OnTaskFinishListener{
void onFinish();
}
and then implement this interface in your caller class:
public class YourActivity extends Activity implements OnTaskFinishListener {
void onFinish(){
Intent intent = new Intent(LoginMember.this, WelcomeScreen.class);
startActivity(intent);
}
}
When you create asynctask you should pass this reference as a parameter in its constructor and keep it in task fields and when the task is done call the onFinish method.
public EndpointsAsyncTaskInsert extends AsyncTask...{
private OnTaskFinishListener listener;
public EndpointsAsyncTaskInsert(OnTaskFinishListener listener){
this.listener = listener;
}
protected void onPostExecute(..){
//notify the listener
listener.onFinish();
}
}
Second and more loosely coupled way is to use an event bus library, for example, greenrobots EventBus https://github.com/greenrobot/EventBus, then you can post an event when your task is finished, and then you can receive that event in your activity without setting up any listeners.
You can make an anonymous version of your AsyncTask class and override the onPostExecute to start the new activity after it is done.
new EndpointsAsyncTaskInsert(LoginMember.this) {
protected void onPostExecute(User result) {
super.onPostExecute(result);
// Do something with result
Intent intent = new Intent(LoginMember.this, WelcomeScreen.class);
startActivity(intent);
}
}.execute(params);
Maybe this might work
if ((txtEmail.length() == 0) || (txtPassword.length() == 0)) {
Toast.makeText(LoginMember.this, "You need to provide values for Email and Password", Toast.LENGTH_SHORT).show();
return;
}
else{
String[] params = {email,password};
new EndpointsAsyncTaskInsert(LoginMember.this).execute(params);
}
In the class which extends the Asynctask override the onpostexecute method and add the following code
Intent in=new Intent(Login.this,Welcome.class);
in.putExtra("email",email);
in.putExtra("password",password);
startActivity(in);
You can use bundle to send data from one activity to another and retrieve from the bundle in the Welcome activity
Intent in=getIntent();
String email=in.getStringExtra("email");
I am trying to develop a simple app that when I buy an activity it makes the button enabled.
My code works fine but the problem is when I exit the app and reopen it, the buttons that was previously enabled after the purchase they become disabled however it doesn't allow to repurchase again.
(I need to do it on time purchase)
So how to keep the enabled buttons stays enabled when I restart the app?
Here is my code:
public class MainScreen extends ActionBarActivity {
private static final String TAG = "com.aseng90_test.smiap2";
IabHelper mHelper;
static final String ITEM_SKU = "com.aseng90_test.smiap2_button5";
static final String ITEM_SKU2 = "com.aseng90_test.smiap2_buyact2";
static final String ITEM_SKU3 = "com.aseng90_test.smiap2_buyact3";
static final String ITEM_SKU4 = "com.aseng90_test.smiap2_buyall";
public Button Activity1;
public Button Activity2;
public Button Activity3;
public Button buyButton;
public Button buyAct2;
public Button buyAct3;
public Button buyAll;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
buyButton = (Button) findViewById(R.id.buyButton);
buyAct2 = (Button) findViewById(R.id.buyact2);
buyAct3 = (Button) findViewById(R.id.buyact3);
buyAll = (Button) findViewById(R.id.buyall);
Activity1 = (Button) findViewById(R.id.act1);
Activity2 = (Button) findViewById(R.id.act2);
Activity3 = (Button) findViewById(R.id.act3);
Activity1.setEnabled(false);
Activity2.setEnabled(false);
Activity3.setEnabled(false);
String base64EncodedPublicKey =
"";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.startSetup(new
IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result)
{
if (!result.isSuccess()) {
Log.d(TAG, "In-app Billing setup failed: " +
result);
} else {
Log.d(TAG, "In-app Billing is set up OK");
}
}
});
}
public void buyClick(View view) {
mHelper.launchPurchaseFlow(this, ITEM_SKU, 10001,
mPurchaseFinishedListener, "mypurchasetoken");
}
public void buyAct2 (View view){
mHelper.launchPurchaseFlow(this, ITEM_SKU2, 10002, mPurchaseFinishedListener, "buyact2");
}
public void buyAct3 (View view){
mHelper.launchPurchaseFlow(this,ITEM_SKU3, 10003, mPurchaseFinishedListener, "buyact3");
}
public void buyAll (View view){
mHelper.launchPurchaseFlow(this, ITEM_SKU4,10004, mPurchaseFinishedListener, "buyall");
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data)
{
if (!mHelper.handleActivityResult(requestCode,
resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
= new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result,
Purchase purchase)
{
if (result.isFailure()) {
// Handle error
return;
}
if (purchase.getSku().equals(ITEM_SKU)) {
Activity1.setEnabled(true);
buyButton.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU2)){
Activity2.setEnabled(true);
buyAct2.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU3)){
Activity3.setEnabled(true);
buyAct3.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU4)) {
Activity1.setEnabled(true);
Activity2.setEnabled(true);
Activity3.setEnabled(true);
buyAll.setEnabled(false);
buyButton.setEnabled(false);
buyAct2.setEnabled(false);
buyAct3.setEnabled(false);
}
}
};
public void Activity1 (View view)
{
startActivity(new Intent(MainScreen.this, Click1.class));
}
public void Activity2 (View view){
startActivity(new Intent(MainScreen.this, Activity2.class));
}
public void Activity3 (View view){
startActivity(new Intent(MainScreen.this, Activity3.class));
}
#Override
public void onDestroy() {
super.onDestroy();
if (mHelper != null ) mHelper.dispose();
mHelper = null ;
}
Thanks a lot
Ok so I used shared preference to save my activity state but it only works fine when I try to enable a button with another free button, but it doesn't work with the in app purchase button (simply it let me do the purchase but the deactivated button never turns enabled after the purchase) So I don't know if there is a conflict between in app purchase and shared preference in my code?
Here is my edited code:
package com.aseng90_test.smiap2;
import android.content.Intent; import
android.content.SharedPreferences; import
android.support.v7.app.ActionBarActivity; import android.os.Bundle;
import android.util.Log; import android.view.View; import
android.widget.Button; import android.widget.Toast;
import com.aseng90_test.smiap2.util.IabHelper; import
com.aseng90_test.smiap2.util.IabResult; import
com.aseng90_test.smiap2.util.Purchase;
public class MainScreen extends ActionBarActivity {
private static final String TAG = "com.aseng90_test.smiap2";
IabHelper mHelper;
static final String ITEM_SKU = "com.aseng90_test.smiap2_button55";
static final String ITEM_SKU2 = "com.aseng90_test.smiap2_buyact22";
static final String ITEM_SKU3 = "com.aseng90_test.smiap2_buyact33";
static final String ITEM_SKU4 = "com.aseng90_test.smiap2_buyall_1";
private Button Activity1;
private Button Activity2;
private Button Activity3;
private Button buyButton;
private Button buyAct2;
private Button buyAct3;
private Button buyAll;
private Button EAct4; private Button Act4;
private SharedPreferences prefs;
private String prefName = "MyPref";
boolean Activity1_isEnabled;
boolean Activity2_isEnabled;
boolean Activity3_isEnabled;
boolean Act4_isEnabled;
boolean buyButton_isEnabled;
boolean buyAct2_isEnabled;
boolean buyAct3_isEnabled;
boolean buyAll_isEnabled;
boolean EAct4_isEnabled;
private static final String Activity1_state = "Activity1_state";
private static final String Activity2_State = "Activity2_state";
private static final String Activity3_State = "Activity3_state";
private static final String buyButton_State = "buyButton_state";
private static final String buyAct2_State = "buyAct2_state";
private static final String buyAct3_State = "buyAct3_state";
private static final String buyAll_State = "buyAll_state";
private static final String Act4_State = "Act4_state";
private static final String EAct4_State = "EAct4_state";
public void buyClick(View view) {
mHelper.launchPurchaseFlow(this, ITEM_SKU, 10001,
mPurchaseFinishedListener, "mypurchasetoken");
}
public void buyAct2 (View view){
mHelper.launchPurchaseFlow(this, ITEM_SKU2, 10002, mPurchaseFinishedListener, "buyact2");
}
public void buyAct3 (View view){
mHelper.launchPurchaseFlow(this,ITEM_SKU3, 10003, mPurchaseFinishedListener, "buyact3");
}
public void buyAll (View view){
mHelper.launchPurchaseFlow(this, ITEM_SKU4,10004, mPurchaseFinishedListener, "buyall");
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
buyButton = (Button) findViewById(R.id.buyButton);
buyAct2 = (Button) findViewById(R.id.buyact2);
buyAct3 = (Button) findViewById(R.id.buyact3);
buyAll = (Button) findViewById(R.id.buyall);
Activity1 = (Button) findViewById(R.id.act1);
Activity2 = (Button) findViewById(R.id.act2);
Activity3 = (Button) findViewById(R.id.act3);
EAct4 = (Button) findViewById(R.id.eact4);
Act4 = (Button) findViewById(R.id.act4);
String base64EncodedPublicKey =
"";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.startSetup(new
IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result)
{
if (!result.isSuccess()) {
Log.d(TAG, "In-app Billing setup failed: " + result);
} else {
Log.d(TAG, "In-app Billing is set up OK");
}
}
});
}
public void EACT4 (View view) {
EAct4.setEnabled(false);
Act4.setEnabled(true);
}
public void ACT4 (View view){
Toast.makeText(MainScreen.this,
"ACt4 Clicked", Toast.LENGTH_LONG).show();
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data)
{
if (!mHelper.handleActivityResult(requestCode,
resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
= new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result,
Purchase purchase)
{
if (result.isFailure()) {
// Handle error
return;
}
if (purchase.getSku().equals(ITEM_SKU)) {
Activity1.setEnabled(true);
buyButton.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU2)){
Activity2.setEnabled(true);
buyAct2.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU3)){
Activity3.setEnabled(true);
buyAct3.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU4)) {
Activity1.setEnabled(true);
Activity2.setEnabled(true);
Activity3.setEnabled(true);
buyAll.setEnabled(false);
buyButton.setEnabled(false);
buyAct2.setEnabled(false);
buyAct3.setEnabled(false);
}
}
};
public void Activity1 (View view)
{
startActivity(new Intent(MainScreen.this, Click1.class));
}
public void Activity2 (View view){
startActivity(new Intent(MainScreen.this, Activity2.class));
}
public void Activity3 (View view){
startActivity(new Intent(MainScreen.this, Activity3.class));
}
#Override
public void onDestroy() {
super.onDestroy();
if (mHelper != null ) mHelper.dispose();
mHelper = null ;
}
#Override
protected void onPause(){
super.onPause();
if (Act4.isEnabled()){
Act4_isEnabled = true;
}
else {
Act4_isEnabled = false;
}
if (Activity1.isEnabled()){
Activity1_isEnabled = true;
}
else {
Activity1_isEnabled = false;
}
if (Activity2.isEnabled()){
Activity2_isEnabled = true;
}
else {
Activity2_isEnabled = false;
}
if (Activity3.isEnabled()){
Activity3_isEnabled = true;
}
else {
Activity3_isEnabled = false;
}
if (buyButton.isEnabled()){
buyButton_isEnabled = true;
}
else {
buyButton_isEnabled = false;
}
if (buyAct2.isEnabled()){
buyAct2_isEnabled = true;
}
else {
buyAct2_isEnabled = false;
}
if (buyAct3.isEnabled()){
buyAct3_isEnabled = true;
}
else {
buyAct3_isEnabled = false;
}
if (buyAll.isEnabled()){
buyAll_isEnabled = true;
}
else {
buyAll_isEnabled = false;
}
prefs = getSharedPreferences(prefName,MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(Act4_State,Act4_isEnabled);
editor.putBoolean(EAct4_State,EAct4_isEnabled);
editor.putBoolean(Activity1_state,Activity1_isEnabled);
editor.putBoolean(Activity2_State,Activity2_isEnabled);
editor.putBoolean(Activity3_State,Activity3_isEnabled);
editor.putBoolean(buyButton_State,buyButton_isEnabled);
editor.putBoolean(buyAct2_State,buyAct2_isEnabled);
editor.putBoolean(buyAct3_State,buyAct3_isEnabled);
editor.putBoolean(buyAll_State,buyAll_isEnabled);
editor.apply();
}
#Override
protected void onResume(){
super.onResume();
prefs = getSharedPreferences(prefName,MODE_PRIVATE);
Act4.setEnabled(prefs.getBoolean(Act4_State,false));
Activity1.setEnabled(prefs.getBoolean(Activity1_state,false));
Activity2.setEnabled(prefs.getBoolean(Activity2_State,false));
Activity3.setEnabled(prefs.getBoolean(Activity3_State,false));
EAct4.setEnabled(prefs.getBoolean(EAct4_State,true));
buyButton.setEnabled(prefs.getBoolean(buyButton_State,true));
buyAct2.setEnabled(prefs.getBoolean(buyAct2_State,true));
buyAct3.setEnabled(prefs.getBoolean(buyAct3_State,true));
buyAll.setEnabled(prefs.getBoolean(buyAll_State,true));
}
Thanks again
When your activity is restarted, it does not save the state of its views from the previous instance. Thus you probably need to save your state data somewhere so that when you restart your activity, you can then reset your views looking at this saved state data.You can make use of "SharedPreferences" class. SharedPreferences lets you store information in key-value pair. I guess that serves your purpose.
SharedPreferences pref = getApplicationContext().getSharedPreferences("ProductCache", 0);
// 0 - for private mode
//First parameter is the name of your preference file.Could be "ProductCache" in your case.
// Default 0 for private access.
SharedPreferences.Editor editor = pref.edit(); // edit your preference file
editor.putString("KEY","VALUE");//save strings
editor.putBoolean("KEY",true);//save booleans or any other type of data.
editor.commit(); //commit your changes
You can set that your product is already bought in your mPurchaseFinishedListener.Next time your app is opened you can check the same file by using the same "keys" that you used to store information to check if the product is already bought and then you can set your views accordingly.
If this doesn't serve your purpose, then you might have to start implementing a SQLite database that keeps track of all purchases. Please go through this article on Android Developers as it might help you further:
http://developer.android.com/training/basics/data-storage/index.html
Hope this helps. Cheers!
Use CheckOut library it does everything for you, you can check for the purchased items and based on the sku you can enable or disable purchase button.
I am trying to develop an app with in app purchases in it, simply what I want to do is to have two buttons one to make the purchase(enabled) the second button to open the activity after purchase (at first is disabled then after purchase is enabled).
Two problems the first was to save the buttons state after the purchase as they were getting reset every time I restart the app. So I did some researches and found about shared preference and I did implemented it but the second problem came out that buttons statuses doesn’t seem to work right (between disabled to enabled) after implementing shared preference.
Note that in the app I have two buttons that do the same thing one enables the other buttons but with no purchase made and they work fine with shared preference, but the buttons associated with the in app purchase stopped changing their status from disabled to enabled after the purchase is made (they stay disabled after the purchase)
Here is my xml code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainScreen">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Activity 1"
android:id="#+id/act1"
android:onClick="Activity1"
android:layout_marginTop="84dp"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/buyall"
android:layout_toStartOf="#+id/buyall"
android:enabled="false" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Buy Act 1"
android:id="#+id/buyButton"
android:onClick="buyClick"
android:layout_alignTop="#+id/act1"
android:layout_toRightOf="#+id/act1"
android:layout_toEndOf="#+id/act1"
android:layout_marginLeft="45dp"
android:layout_marginStart="45dp"
android:enabled="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Activity 2"
android:id="#+id/act2"
android:layout_below="#+id/act1"
android:layout_alignLeft="#+id/act1"
android:layout_alignStart="#+id/act1"
android:onClick="Activity2"
android:enabled="false" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Buy act 2"
android:id="#+id/buyact2"
android:layout_alignBottom="#+id/act2"
android:layout_alignLeft="#+id/buyButton"
android:layout_alignStart="#+id/buyButton"
android:onClick="buyAct2"
android:enabled="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Activity 3"
android:id="#+id/act3"
android:layout_below="#+id/act2"
android:layout_alignLeft="#+id/act2"
android:layout_alignStart="#+id/act2"
android:onClick="Activity3"
android:enabled="false" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Buy act 3"
android:id="#+id/buyact3"
android:layout_alignBottom="#+id/act3"
android:layout_alignLeft="#+id/buyact2"
android:layout_alignStart="#+id/buyact2"
android:onClick="buyAct3"
android:enabled="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Buy all"
android:id="#+id/buyall"
android:onClick="buyAll"
android:enabled="true"
android:layout_below="#+id/eact4"
android:layout_centerHorizontal="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ACT 4"
android:id="#+id/act4"
android:onClick="ACT4"
android:layout_below="#+id/act3"
android:layout_alignLeft="#+id/act3"
android:layout_alignStart="#+id/act3"
android:enabled="false" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Enable ACT 4"
android:id="#+id/eact4"
android:onClick="EACT4"
android:layout_below="#+id/buyact3"
android:layout_alignLeft="#+id/buyact3"
android:layout_alignStart="#+id/buyact3"
android:enabled="true" />
And that’s my java code:
package com.aseng90_test.smiap2;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.aseng90_test.smiap2.util.IabHelper;
import com.aseng90_test.smiap2.util.IabResult;
import com.aseng90_test.smiap2.util.Purchase;
public class MainScreen extends ActionBarActivity {
private static final String TAG = "com.aseng90_test.smiap2";
IabHelper mHelper;
private static final String ITEM_SKU = "com.aseng90_test.smiap2_button555";
private static final String ITEM_SKU2 = "com.aseng90_test.smiap2_buyact222";
private static final String ITEM_SKU3 = "com.aseng90_test.smiap2_buyact333";
private static final String ITEM_SKU4 = "com.aseng90_test.smiap2_buyall_11";
private Button Activity1;
private Button Activity2;
private Button Activity3;
private Button buyButton;
private Button buyAct2;
private Button buyAct3;
private Button buyAll;
private Button EAct4;
private Button Act4;
private SharedPreferences prefs;
private String prefName = "MyPref";
boolean Activity1_isEnabled;
boolean Activity2_isEnabled;
boolean Activity3_isEnabled;
boolean Act4_isEnabled;
boolean buyButton_isEnabled;
boolean buyAct2_isEnabled;
boolean buyAct3_isEnabled;
boolean buyAll_isEnabled;
boolean EAct4_isEnabled;
private static final String Activity1_state = "Activity1_state";
private static final String Activity2_State = "Activity2_state";
private static final String Activity3_State = "Activity3_state";
private static final String buyButton_State = "buyButton_state";
private static final String buyAct2_State = "buyAct2_state";
private static final String buyAct3_State = "buyAct3_state";
private static final String buyAll_State = "buyAll_state";
private static final String Act4_State = "Act4_state";
private static final String EAct4_State = "EAct4_state";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
buyButton = (Button) findViewById(R.id.buyButton);
buyAct2 = (Button) findViewById(R.id.buyact2);
buyAct3 = (Button) findViewById(R.id.buyact3);
buyAll = (Button) findViewById(R.id.buyall);
Activity1 = (Button) findViewById(R.id.act1);
Activity2 = (Button) findViewById(R.id.act2);
Activity3 = (Button) findViewById(R.id.act3);
EAct4 = (Button) findViewById(R.id.eact4);
Act4 = (Button) findViewById(R.id.act4);
String base64EncodedPublicKey =
"";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.startSetup(new
IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
Log.d(TAG, "In-app Billing setup failed: " + result);
} else {
Log.d(TAG, "In-app Billing is set up OK");
}
}
});
}
public void EACT4(View view) {
EAct4.setEnabled(false);
Act4.setEnabled(true);
}
public void ACT4(View view) {
Toast.makeText(MainScreen.this,
"ACt4 Clicked", Toast.LENGTH_LONG).show();
}
public void buyClick(View view) {
mHelper.launchPurchaseFlow(this, ITEM_SKU, 10001,
mPurchaseFinishedListener, "mypurchasetoken");
}
public void buyAct2(View view) {
mHelper.launchPurchaseFlow(this, ITEM_SKU2, 10002, mPurchaseFinishedListener, "buyact2");
}
public void buyAct3(View view) {
mHelper.launchPurchaseFlow(this, ITEM_SKU3, 10003, mPurchaseFinishedListener, "buyact3");
}
public void buyAll(View view) {
mHelper.launchPurchaseFlow(this, ITEM_SKU4, 10004, mPurchaseFinishedListener, "buyall");
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (!mHelper.handleActivityResult(requestCode,
resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
= new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result,
Purchase purchase) {
if (result.isFailure()) {
// Handle error
return;
}
if (purchase.getSku().equals(ITEM_SKU)) {
Activity1.setEnabled(true);
buyButton.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU2)) {
Activity2.setEnabled(true);
buyAct2.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU3)) {
Activity3.setEnabled(true);
buyAct3.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU4)) {
Activity1.setEnabled(true);
Activity2.setEnabled(true);
Activity3.setEnabled(true);
buyAll.setEnabled(false);
buyButton.setEnabled(false);
buyAct2.setEnabled(false);
buyAct3.setEnabled(false);
}
}
};
public void Activity1(View view) {
startActivity(new Intent(MainScreen.this, Click1.class));
}
public void Activity2(View view) {
startActivity(new Intent(MainScreen.this, Activity2.class));
}
public void Activity3(View view) {
startActivity(new Intent(MainScreen.this, Activity3.class));
}
#Override
public void onDestroy() {
super.onDestroy();
if (mHelper != null) mHelper.dispose();
mHelper = null;
}
#Override
protected void onPause(){
super.onPause();
if (Act4.isEnabled()){
Act4_isEnabled = true;
}
else {
Act4_isEnabled = false;
}
if (Activity1.isEnabled()){
Activity1_isEnabled = true;
}
else {
Activity1_isEnabled = false;
}
if (Activity2.isEnabled()){
Activity2_isEnabled = true;
}
else {
Activity2_isEnabled = false;
}
if (Activity3.isEnabled()){
Activity3_isEnabled = true;
}
else {
Activity3_isEnabled = false;
}
if (buyButton.isEnabled()){
buyButton_isEnabled = true;
}
else {
buyButton_isEnabled = false;
}
if (buyAct2.isEnabled()){
buyAct2_isEnabled = true;
}
else {
buyAct2_isEnabled = false;
}
if (buyAct3.isEnabled()){
buyAct3_isEnabled = true;
}
else {
buyAct3_isEnabled = false;
}
if (buyAll.isEnabled()){
buyAll_isEnabled = true;
}
else {
buyAll_isEnabled = false;
}
prefs = getSharedPreferences(prefName,MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(Activity1_state,this.getLocalClassName());
editor.putBoolean(Act4_State,Act4_isEnabled);
editor.putBoolean(EAct4_State,EAct4_isEnabled);
editor.putBoolean(Activity1_state,Activity1_isEnabled);
editor.putBoolean(Activity2_State,Activity2_isEnabled);
editor.putBoolean(Activity3_State,Activity3_isEnabled);
editor.putBoolean(buyButton_State,buyButton_isEnabled);
editor.putBoolean(buyAct2_State,buyAct2_isEnabled);
editor.putBoolean(buyAct3_State,buyAct3_isEnabled);
editor.putBoolean(buyAll_State,buyAll_isEnabled);
editor.apply();
}
#Override
protected void onResume(){
super.onResume();
prefs = getSharedPreferences(prefName,MODE_PRIVATE);
Act4.setEnabled(prefs.getBoolean(Act4_State,false));
Activity1.setEnabled(prefs.getBoolean(Activity1_state,false));
Activity2.setEnabled(prefs.getBoolean(Activity2_State,false));
Activity3.setEnabled(prefs.getBoolean(Activity3_State,false));
EAct4.setEnabled(prefs.getBoolean(EAct4_State,true));
buyButton.setEnabled(prefs.getBoolean(buyButton_State,true));
buyAct2.setEnabled(prefs.getBoolean(buyAct2_State,true));
buyAct3.setEnabled(prefs.getBoolean(buyAct3_State,true));
buyAll.setEnabled(prefs.getBoolean(buyAll_State,true));
}
So Any suggestions if I have something wrong in my code?
Thanks a lot.
Try to call methods from Java part , don't call from xml using android:onClick
Use default value of the button(buy) state to false in shared preference .
and in this screen implement this if check inside oncreate() method as:
if(button(buy) state ==false)
{
//make button(buy) state enable
//make activity button state disable
}
else
{
//make button(buy) state disable
//make activity button state enable
}
And make button(buy) and activity calling button state to true/false according to result after in app purchase and also update shared prefrence state according to result