Android - Error Thread and a button still clickable - java

READ THIS : I want to like this.... if user have input name and choose game types. user can click 'OK' button. if user haven't input name and choose game types he can't click 'OK' button.
I create thread to solve this problem...
But when I run this app. I can't go to this UI again..
Something wrong in method 'autoValidation'
And code userConfigOK.setClickable(false); doesn't work. I don't know why..
btw, android is hard. . . .
This is the source code :
public class UserConfig extends Activity {
private String gameType;
private String gameTime;
private String playerName;
private int IDChar = 0;
Thread validation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.user_config);
userConfigOK.setClickable(false);
inputName();
chooseCharacter();
setGameType();
back();
autoValidation();
OK();
}
public void inputName() {
playerName = userNameTextbox.getText().toString();
}
public void setGameType() {
gameTypes.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View arg1,
int arg2, long arg3) {
gameType = (String) gameTypes.getSelectedItem();
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
}
public void OK() {
userConfigOK.setOnClickListener( new OnClickListener() {
#SuppressWarnings("deprecation")
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(UserConfig.this, EnemyConfig1.class);
startActivity(intent);
validation.stop();
}
});
}
public void autoValidation() {
validation = new Thread(new Runnable() {
#Override
public void run() {
if( ( !gameType.trim().equals("") ) && ( !playerName.trim().equals("") ) )
{
userConfigOK.setClickable(true);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
validation.start();
}
}

Try this
userConfigOK.setEnabled(false);
Instead of
userConfigOK.setClickable(false);

You could just have the onClickListener check to see if there is any text entered, and if there is an item selected from the grid. If the user hasn't selected anything, you could make a Toast that prompts the user to enter the values required.

Related

setOnUtteranceProgressListener not at all working for Text To Speech for API > 21

I want setOnUtteranceProgressListener should notify a Toast after the speech is completed.It seems not working.
I have used setOnUtteranceProgressListener and on the speak function i have mentioned the paramaters as follows..
Bundle params = new Bundle();
params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, MainActivity.this.getPackageName());
I have given a "UniqueId" while calling speak function as follows.
myTTS.speak(message,TextToSpeech.QUEUE_FLUSH,params,"UniqueId");
In My program after the text to speech engine finishes speaking it should run a Toast notifying that it has finished speaking.But the setOnUtteranceProgressListner seems not working.
myTTS.setOnUtteranceProgressListener(new UtteranceProgressListener() {
#Override
public void onStart(String utteranceId) {
}
#Override
public void onDone(String utteranceId) {
Toast.makeText(MainActivity.this,"Finished speaking.",Toast.LENGTH_LONG).show();
}
#Override
public void onError(String utteranceId) {
}
});
The all Code is as follows..
public class MainActivity extends AppCompatActivity {
String message;
private TextToSpeech myTTS;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myTTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(myTTS.getEngines().size() == 0){
Toast.makeText(MainActivity.this,"No Engines Installed",Toast.LENGTH_LONG).show();
}else{
myTTS.setLanguage(Locale.US);
if (status == TextToSpeech.SUCCESS){
//Toast.makeText(MainActivity.this,"Status working.",Toast.LENGTH_LONG).show();
message = "How may i help you.";
}
}
}
});
myTTS.setOnUtteranceProgressListener(new UtteranceProgressListener() {
#Override
public void onStart(String utteranceId) {
}
#Override
public void onDone(String utteranceId) {
Toast.makeText(MainActivity.this,"onDone working.",Toast.LENGTH_LONG).show();
}
#Override
public void onError(String utteranceId) {
}
});
}
Please give a solution for this.
The main problems are:
1) Setting the progress listener before the tts is initialized.
2) Trying to make a Toast from a background thread.
I also have some other suggested changes but they are not required:
public class MainActivity extends AppCompatActivity {
String message = "How may I help you?";
String mostRecentUtteranceID;
private TextToSpeech myTTS;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myTTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(myTTS.getEngines().size() == 0){
Toast.makeText(MainActivity.this,"No Engines Installed",Toast.LENGTH_LONG).show();
}else{
if (status == TextToSpeech.SUCCESS){
ttsInitialized();
}
}
}
});
}
private void ttsInitialized() {
// *** set UtteranceProgressListener AFTER tts is initialized ***
myTTS.setOnUtteranceProgressListener(new UtteranceProgressListener() {
#Override
public void onStart(String utteranceId) {
}
#Override
// this method will always called from a background thread.
public void onDone(String utteranceId) {
// only respond to the most recent utterance
if (!utteranceId.equals(mostRecentUtteranceID)) {
Log.i("XXX", "onDone() blocked: utterance ID mismatch.");
return;
} // else continue...
boolean wasCalledFromBackgroundThread = (Thread.currentThread().getId() != 1);
Log.i("XXX", "was onDone() called on a background thread? : " + wasCalledFromBackgroundThread);
Log.i("XXX", "onDone working.");
// for demonstration only... avoid references to
// MainActivity (unless you use a WeakReference)
// inside the onDone() method, as it
// can cause a memory leak.
runOnUiThread(new Runnable() {
#Override
public void run() {
// *** toast will not work if called from a background thread ***
Toast.makeText(MainActivity.this,"onDone working.",Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onError(String utteranceId) {
}
});
// set Language
myTTS.setLanguage(Locale.US);
// set unique utterance ID for each utterance
mostRecentUtteranceID = (new Random().nextInt() % 9999999) + ""; // "" is String force
// set params
// *** this method will work for more devices: API 19+ ***
HashMap<String, String> params = new HashMap<>();
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, mostRecentUtteranceID);
myTTS.speak(message,TextToSpeech.QUEUE_FLUSH,params);
}
}
If you want to add the call back OnUtteranceProgressListener you have to implement the speak method like this:
myTTS.speak(message,TextToSpeech.QUEUE_FLUSH, null , TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID);
Then it will call the methods that you've already implemented (onStart, onDone, etc)

How to make the text fade for seconds

How to make the text fade for only 20 seconds and then disappear when you click the button
This is the code
public void scoreOpenB(View v) {
findViewById(R.id.main_mess).setVisibility(View.GONE);
((TextView)findViewById(R.id.main_mess)).setText(R.string.btn_closs);
findViewById(R.id.main_mess).setVisibility(View.VISIBLE );
}
}
You can use AsyncTask to update UI after delay. Try this ;)
public void scoreOpenB(View v) {
View updateMe = findViewById(R.id.main_mess);
updateMe.setVisibility(View.GONE);
new UpdateUI().execute(updateMe);
}
}
private class updateUI extends AsyncTask<View, Integer, Long> {
View toUpdate;
protected void doInBackground(View view) {
toUpdate = view;
try {
Thread.sleep(20000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(Long result) {
(toUpdate(TextView)).setText(R.string.btn_closs);
toUpdate.setVisibility(View.VISIBLE);
}
}

Android - False when make thread

I want: if user already put name and choose game types, user can click button 'OK' but if user doesn't already put name and choose game types, user can't click button 'OK'.
public class UserConfig extends Activity {
Button userConfigBack;
Button userConfigOK;
EditText userNameTextbox;
Spinner gameTypes;
private String gameType;
private String playerName;
private Handler handler;
Thread validation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.user_config);
userConfigBack = (Button) findViewById(R.id.user_config_back);
userConfigOK = (Button) findViewById(R.id.user_config_ok);
userNameTextbox = (EditText) findViewById(R.id.user_name_textbox);
gameTypes = (Spinner) findViewById(R.id.game_types);
gameTimes = (Spinner) findViewById(R.id.game_times);
userConfigOK.setEnabled(false);
userConfigOK.setClickable(false);
setName();
setGameType();
handler = new Handler();
autoValidation();
OK();
}
public void setName() {
playerName = userNameTextbox.getText().toString();
userNameTextbox.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
playerName = userNameTextbox.getText().toString();
nameLabel.setText(playerName);
}
#Override
public void afterTextChanged(Editable arg0) {
}
});
}
public void setGameType() {
gameTypes.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View arg1,
int arg2, long arg3) {
gameType = (String) gameTypes.getSelectedItem();
gameTypeLabel.setText(gameType);
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
}
public void OK() {
userConfigOK.setOnClickListener( new OnClickListener() {
#SuppressWarnings("deprecation")
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(UserConfig.this, EnemyConfig1.class);
startActivity(intent);
}
});
}
public void autoValidation() {
validation = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
#Override
public void run() {
if(!gameType.equals("")) {
if(!playerName.equals("")) {
userConfigOK.setEnabled(true);
userConfigOK.setClickable(true);
}
}
}
});
}
});
validation.start();
}
}
I create thread inside method AUTOVALIDATION. If editText not null and user already choose game types spinner, user can click button OK. But
userConfigOK.setEnabled(true);
userConfigOK.setClickable(true);
doesn't work.
You can't change any UI elements from another Thread. Try to use a runOnUiThread this should solve the problem.
You really should read this carefully: http://developer.android.com/guide/components/processes-and-threads.html This will save you al lot of time if you are working with Threads.
And here is an example that helped me a lot:
how to use runOnUiThread
add a text watcher to your edittext and then use this if elsestatement:
if(!userNameTextbox.getText().toString().equals("")){
//do your job
}else{
//Toast some thing
}

How do I release my media player after it is done playing?

I am creating a sound board and after clicking about 30 different sounds it stops working; I believe android is running out of memory. Below is my code. How can I implement .release() so that when the sound is done playing it is released? I don't really care if two things play at the same time; the clips are t0o short for this to be possible. I would just like to get my code set.
public class soundPageOne extends Activity {
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
final MediaPlayer pg1 = MediaPlayer.create(this, R.raw.peter1);
Button playSound1 = (Button) this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pg1.start();
}
});
I have done a lot of searching around but due to my lack of java/android knowledge I have not been able to get anything to work. Thanks in advance, let me know if anyone needs anymore code.
I left a comment, but I'll post an answer to show what I mean anyway...
The idea is that you have a set number of MediaPlayer instances that you can use. That way you never exceed the maximum number of instances. The array should be the length of the number of concurrent sounds you expect to be able to hear. If the sounds are local files, the length of time it takes to prepare the sounds should be almost negligible, so calling create inside the click handler should not result in terrible performance. Each of your buttons is associated with a particular resource, I suppose, so I set up a helper method to create and play the sounds for each button in the same way.
public class soundPageOne extends Activity {
private MediaPlayer[] mPlayers = new MediaPlayer[2];
private int mNextPlayer = 0;
#Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
Button playSound1 = (Button)this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startSound(R.raw.peter1);
}
});
}
public void onDestroy() {
super.onDestroy(); // <---------------------- This needed to be there
for (int i = 0; i < mPlayers.length; ++i)
if (mPlayers[i] != null)
try {
mPlayers[i].release();
mPlayers[i] = null;
}
catch (Exception ex) {
// handle...
}
}
private void startSound(int id) {
try {
if (mPlayers[mNextPlayer] != null) {
mPlayers[mNextPlayer].release();
mPlayers[mNextPlayer] = null;
}
mPlayers[mNextPlayer] = MediaPlayer.create(this, id);
mPlayers[mNextPlayer].start();
}
catch (Exception ex) {
// handle
}
finally {
++mNextPlayer;
mNextPlayer %= mPlayers.length;
}
}
}
Create a class, say AudioPlayer with a SoundPool variable. Setup a constructor to initialise the AudioPlayer object and create a Play method. SoundPool works better for short sounds played many times and does not require you to release.
public class AudioPlayer {
private SoundPool sPool = new SoundPool(Integer.MAX_VALUE, AudioManager.STREAM_MUSIC, 0);
public AudioPlayer(Context c, int id){
sounds.put("1",sPool.load(c, id, 1));
}
public void play(Context c) {
sPool.play("1", 1, 1, 1, 0, 1f);
}
}
So your class should look like
public class soundPageOne extends Activity {
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
final AudioPlayer ap = new AudioPlayer(this, R.raw.sound);
Button playSound1 = (Button) this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ap.play();
}
});
Could you use a MediaPlayer.OnCompletionListener?
Something like:
public class soundPageOne extends Activity implements MediaPlayer.OnCompletionListener {
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
final MediaPlayer pg1 = MediaPlayer.create(this, R.raw.peter1);
//***set the listener here***
pg1.setOnCompletionListener(this);
Button playSound1 = (Button) this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pg1.start();
}
});
}
//***this code will be executed once the sound finishes playing***
#Override
public void onCompletion(MediaPlayer mp) {
//log messages, other things can go here
mp.release();
}
Try something like this
Your activity class:
public class soundPageOne extends Activity {
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
final AudioPlayer pg1 = new AudioPlayer();
Button playSound1 = (Button) this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pg1.play(this, R.raw.sound);
}
});
}
This is another Java Class:
public class AudioPlayer {
private MediaPlayer mPlayer;
public void stop() {
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
public void play(Context c, int sound) {
stop();
mPlayer = MediaPlayer.create(c, sound);
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
stop();
}
});
mPlayer.start();
}
public boolean isPlaying() {
return mPlayer != null;
}
}

Got error 101, "invalid application id" at Android Facebook Logout

I have a class which extends ListFragment. MyloginToFacebook()method (see below) works. But once I want to logout and call logoutFromFacebook(), I receive the following error:
{"error_code":101,"error_msg":"Invalid application ID.","request_args":[{"key":"method","value":"auth.expireSession"},{"key":"format","value":"json"}]}
Here are my methods:
public void loginToFacebook() {
mPrefs = getPreferences(MODE_PRIVATE);
String access_token = mPrefs.getString("access_token", null);
long expires = mPrefs.getLong("access_expires", 0);
if (access_token != null) {
facebook.setAccessToken(access_token);
btnFbLogin.setVisibility(View.INVISIBLE);
// Making get profile button visible
btnFbGetProfile.setVisibility(View.VISIBLE);
// Making post to wall visible
btnPostToWall.setVisibility(View.VISIBLE);
// Making show access tokens button visible
btnShowAccessTokens.setVisibility(View.VISIBLE);
btnLogout.setVisibility(View.VISIBLE);
Log.d("FB Sessions", "" + facebook.isSessionValid());
}
if (expires != 0) {
facebook.setAccessExpires(expires);
}
if (!facebook.isSessionValid()) {
facebook.authorize(getActivity(),
new String[] { "email", "publish_stream" },
new DialogListener() {
#Override
public void onCancel() {
// Function to handle cancel event
}
#Override
public void onComplete(Bundle values) {
// Function to handle complete event
// Edit Preferences and update facebook acess_token
SharedPreferences.Editor editor = mPrefs.edit();
editor.putString("access_token",
facebook.getAccessToken());
editor.putLong("access_expires",
facebook.getAccessExpires());
editor.commit();
// Making Login button invisible
btnFbLogin.setVisibility(View.INVISIBLE);
// Making logout Button visible
btnFbGetProfile.setVisibility(View.VISIBLE);
// Making post to wall visible
btnPostToWall.setVisibility(View.VISIBLE);
// Making show access tokens button visible
btnShowAccessTokens.setVisibility(View.VISIBLE);
btnLogout.setVisibility(View.VISIBLE);
}
#Override
public void onError(DialogError error) {
// Function to handle error
}
#Override
public void onFacebookError(FacebookError fberror) {
// Function to handle Facebook errors
}
});
}
}
//---------------------------//
public void logoutFromFacebook() {
mAsyncRunner.logout(getActivity(), new RequestListener() {
#Override
public void onComplete(String response, Object state) {
Log.d("Logout from Facebook", response);
if (Boolean.parseBoolean(response) == true) {
runOnUiThread(new Runnable() {
#Override
public void run() {
// make Login button visible
btnFbLogin.setVisibility(View.VISIBLE);
// making all remaining buttons invisible
btnFbGetProfile.setVisibility(View.INVISIBLE);
btnPostToWall.setVisibility(View.INVISIBLE);
btnShowAccessTokens.setVisibility(View.INVISIBLE);
btnLogout.setVisibility(View.INVISIBLE);
}
});
}
}
#Override
public void onIOException(IOException e, Object state) {
}
#Override
public void onFileNotFoundException(FileNotFoundException e,
Object state) {
}
#Override
public void onMalformedURLException(MalformedURLException e,
Object state) {
}
#Override
public void onFacebookError(FacebookError e, Object state) {
}
});
}
I just wonder if the cause of the problem is extends ListFragment, because when I tried with extends Activity, it runs well.
Would someone out there help me out to solve this problem? any helps would be appreciated.
Thank you

Categories

Resources