Get ImageView drawable ID and change it with AsyncTask - java

What I want to do: get the id of the src of an ImageView, compare it to the ids of two drawables, and swap them, using AsyncTask (just because I want to understand how it works).
I've read similar questions here, and so far this is what I've got:
public class Main extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView image = (ImageView) findViewById(R.id.img);
Integer integer = (Integer) image.getTag();
}
private class cambiarImagen extends AsyncTask<Integer, Integer, Integer> {
protected void onPreExecute() {
ImageView image = (ImageView) findViewById(R.id.img);
Integer integer = (Integer) image.getTag();
int img1 = R.drawable.zapato;
int img2 = R.drawable.zapatod;
}
#Override
protected Integer doInBackground(Integer... values) {
// parte logica
int num = values[0];
int zapato = values[1];
int zapatod = values[2];
if (num == zapato) {
num = zapatod;
} else if (num == zapatod) {
num = zapato;
}
return num;
}
protected Void onPostExecute(Integer... values) {
int num = values[0];
ImageView image = (ImageView) findViewById(R.id.img);
image.setTag(num);
return null;
}
}
Of course this doesn't work.
1. I don't understand how to get the id of the drawable that ImageView has as its src.
2. I don't understand how the params are passed in AsyncTask; onPreExecute should receive the UI stuff, doInbackground should receive it to compare it and return the drawable int that should be set to the ImageView, and onPreExecute should set it to the ImageView.

I don't understand how to get the id of the drawable that ImageView has as its src.
I haven't had to do this so may not work but you should be able to use
imageView.getDrawable().getId();
I don't understand how the params are passed in AsyncTask;
Whatever you pass in task.execute() is received by doInBackground(). If you call publishProgress() then whatever params are sent there are received by onProgressUpdate(). And the data returned in doInBackground() is received by onPostExecute().
AsyncTask, just so you know, shouldn't be needed for this but I know you said you wanted to learn how to use it. I was a little confused on exactly what specifically you were having trouble with besides these two things so please elaborate if I missed something.
ImageView Docs
AsyncTask Docs
AsyncTask Example (in case it can be helpful)

You should do other task if you like to get to learn ASyncTask.
I would have done a dialog with progress bar or something instead if i wanted to learn ASyncTask.
edit:
As Samus Arin comment on the main post about you should always have track on which image that you are showing. so instead use something like
if(currentImage == R.Drawable.image1){
image.setImageResource(R.Drawable.image2);
}else{
image.setImageResource(R.Drawable.image1);
}

For what it's worth, take a look at what I'm doing with an AsyncTask, maybe it'll give ya some ideas.
This is Monodroid/C# code, not raw Java/Android (but the syntax is extremely close). As such, inner-classes do not get an implicit reference to their containing object, and so I pass one in (called outer in the constructor). I chose to name it "_" as a lexicographical extension to .NET's _member naming convention for private data members.
public class MonthChangeTask : AsyncTask
{
private CalendarView _; // outer class
private DateTime _newMonth;
private bool _refreshInspectionRecordsRemote;
private bool _changingInspector;
private bool _todayButtonPressed;
private Android.App.ProgressDialog _progressDialog;
private IMXController _controller;
private Dictionary<string, string> _paramz;
private DateTime _newSelectedDate;
public MonthChangeTask( CalendarView outer, DateTime newMonth, bool changingInspector, bool refreshInspectionRecordsRemote, bool todayButtonPressed )
{
_ = outer;
_newMonth = newMonth;
_changingInspector = changingInspector;
_refreshInspectionRecordsRemote = refreshInspectionRecordsRemote;
_todayButtonPressed = todayButtonPressed;
}
protected override void OnPreExecute()
{
base.OnPreExecute();
_progressDialog = Android.App.ProgressDialog.Show( _ , "", "Loading Inspections...");
_newSelectedDate = _._calendar.SetMonth(new DateTime(_newMonth.Year, _newMonth.Month, 1));
AppSettingService.SetCalendarDate(_newMonth);
_paramz = new Dictionary<string, string>();
string target = MD.MxNAVIGATION.CONTROLLER.CALENDAR._name;
string action = MD.MxNAVIGATION.CONTROLLER.ACTION.GET;
string command = _refreshInspectionRecordsRemote
? ((int) MD.MxNAVIGATION.CONTROLLER.CALENDAR.Command.RefreshInspectionRecordsRemote).ToString()
: ((int) MD.MxNAVIGATION.CONTROLLER.CALENDAR.Command.RefreshInspectionRecordsLocal).ToString();
string url = target + "/" + action + "/" + command;
_controller = MXContainer.Instance.GetController(url, ref _paramz);
}
protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] #params)
{
if ( _paramz == null )
{
Log.Info(FIDB.TAG_APP, "MonthChangeTask.DoInBackground(): paramz = NULL");
}
else
{
_controller.Load( _paramz );
}
return true;
}
protected override void OnPostExecute(Java.Lang.Object result)
{
base.OnPostExecute(result);
_progressDialog.Dismiss();
_.Model = (CalendarVM)_controller.GetModel();
if (_changingInspector)
{
_._calendar.PermitSwitch = _.Model.Buttons.PermitsVisible;
_._calendar.ComplaintSwitch = _.Model.Buttons.ComplaintsVisible;
_._calendar.ProjectSwitch = _.Model.Buttons.ProjectsVisible;
_._calendar.PeriodicInspectionSwitch = _.Model.Buttons.PeriodicInspectionsVisible;
}
_.UpdateCalendar(_.Model.Inspections);
if( _todayButtonPressed )
{
_._calendar.SelectedDate = _._calendar.CurrentDate;
}
else
{
_._calendar.SelectedDate = _newSelectedDate;
}
_._calendar.Invalidate();
AppSettingService.SetCalendarDate( _._calendar.SelectedDate );
if ( _.Model.IsParcelCacheDownloading )
{
AnimationTask task = new AnimationTask( _ );
task.Execute( new Java.Lang.Object[1] );
}
}
}

Related

How to display many variables in one textView

I'm working on my first project in Android Studio and I got stuck in "how to display different variables in one textView". to be more clear I'm working on an app that requires the user to enter the gender. each gender has its own calculation method. so I want to display the result calculation the user do in the main interface and In one TextView. I've tried many times to do it but the result is "0.0"
I added another textView and assigned each calculation method to one textview I was able to display the two results.
public class Main_Interface extends AppCompatActivity implements View.OnClickListener{
private TextView results;
//private TextView fResults;//this is the second textview that I created.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main__interface);
results = (TextView)findViewById(R.id.results);
if(results.getText().toString().equals("0.0")) {
results.setVisibility(View.INVISIBLE);
}
//fResults = (TextView)findViewById(R.id.fResults);
// if(fResults.getText().toString().equals("0.0")){
// fResults.setVisibility(View.INVISIBLE );
// }
calculateMale();
calculateFemale();
}
public void calculateMale(){
SharedPreferences s = getSharedPreferences("data", Context.MODE_PRIVATE);
double weight = s.getFloat("weight",0.0f);
double height = s.getFloat("height",0.0f);
int age = s.getInt("theDate", 0);
double results2 = 66+(13.7*weight)+(5*height)-(6.8*age);
results.setText(""+results2);
public void calculateFemale(){
SharedPreferences s1 = getSharedPreferences("data", Context.MODE_PRIVATE);
double fWeight = s1.getFloat("fWeight",0.0f);
double fHeight = s1.getFloat("fHeight",0.0f);
int Fage = s1.getInt("theDate", 0);
double results3 = 655 + (9.6 * fWeight) + (1.8 * fHeight) - (4.7 *Fage)
;
fResults.setText(""+results3);
SharedPreferences.Editor editor = s1.edit();
editor.putFloat("results", (float) results3);
editor.commit();
}
}
displaying the calculation in one textview.
You Are calling these two methods before checking these two methods
calculateMale();
calculateFemale();
in onCreate() {
//do this
calculateMale();
calculateFemale();
//Then check the result to make results visible or invisible.
results = (TextView)findViewById(R.id.results);
if(results.getText().toString().equals("0.0")) {
results.setVisibility(View.INVISIBLE);
}
}
You just need to make it clear when the function is being called. What actually happening here is you are checking textView's value even before calculating your required values. So it is throwing 0.0.
Simply call calculateMale(); calculateFemale(); before checking textView's value.
You are printing results before calling the two function. Try this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main__interface);
results = (TextView)findViewById(R.id.results);
calculateMale();
calculateFemale();
if(results.getText().toString().equals("0.0")) {
results.setVisibility(View.INVISIBLE);
}
}
Return the result from calculateMale() and calculateFemale() methods:
String calculateMale = calculateMale();
String calculateFemale = calculateFemale();
results = (TextView)findViewById(R.id.results);
String result = calculateMale.concat(calculateFemale);
if (result.length() >= 0) {
results.setText(result);
} else {
results.setVisibility(View.INVISIBLE);
}

trying to pass an int variable from Activity to Adapter

I'm trying to pass the int pub_or_priv from my Activity1 to Myadapter.
I've looked at posts here and I think I've followed them correctly but it's still not working. The value in my adapter is always 0 whereas it should be 0,1 or 2, as is the case with the value in my Activity1.
Here's what I've done.
In my Activity1 I get "publicorprivate" from my server and convert it to an int with:
//convert public_or_private to an integer
pub_or_priv = Integer.parseInt(obj.getString("publicorprivate"));
For different cells in my recyclerView it will be 0,1 or 2.
Now I want to pass this to my adapter so in my adapter contructor I have:
public MyAdapter(List<Review> reviewUsers, Activity activity, int pub_or_priv) {
this.activity = activity;
the_reviews = reviewUsers;
this.mPub_or_priv = pub_or_priv;
}
And in my Activity1:
pAdapter = new MyAdapter(reviewList, this, pub_or_priv);
Then in MyAdapter:
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
Review r = the_reviews.get(position);
//shared_status will be Just U, Private or Public
String shared_status ="";
if(mPub_or_priv==0){
//change colour depending on value
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#DA850B"));
shared_status = "Just U";
}
if(mPub_or_priv==1){
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#0A7FDA"));
shared_status = "Private";
}
if(mPub_or_priv==2){
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#2AB40E"));
shared_status = "Public";
}
((ReviewHolder) viewHolder).phone_user_name.setText(shared_status);
etc..etc..
However in the recyclerView in all cells the phone_user_name textbox is always "Just U", in the #DA850B colour, whereas in fact it is supposed to be Private and Public in some cells, as per the pub_or_priv value in Activity1.
How can I get pub_or_priv correctly into my adapter?, thanks.
It looks like you're using one value in the activity/adapter, so of course all rows show the same value.
In the adapter, use the value in the Review instance that corresponds to the current cell:
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
Review review = the_reviews.get(position);
int pubOrPriv = review.getPublicOrPrivate();
//shared_status will be Just U, Private or Public
String shared_status = "";
if (pubOrPriv == 0) {
//change colour depending on value
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#DA850B"));
shared_status = "Just U";
}
if (pubOrPriv == 1) {
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#0A7FDA"));
shared_status = "Private";
}
if (pubOrPriv == 2) {
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#2AB40E"));
shared_status = "Public";
}
//.............
}

How correctly apply MVP pattern in my sample

I decide to learn about MVP pattern and after look through some articles i want to try it with my current project.
I have choosen one activity and begin to think how i can decouple it according MVP rules. And eventually I don't know how to do it. It seems like a not complicated activity but I don't know
Could please someone adviced me with what I have to start?
Which methods have to be in presenter, witch view have to be left in this current activity and whitch methods have to be in interface?
Just advised me who i supposed to begin.
This is my class
public final class ActivityUserDataScreen extends AppCompatActivity implements InterfaceActivityUserDataScreen{
private static String gender;
private static int inputHeight;
private static int inputWeight;
private TextInputLayout tilUserName;
private int backPressedQ = 0;
private String avatarName;
private static final String MEN = "men";
private static final String WOMEN = "men";
private Context context;
private PresenterActivityUserDataScreen presenter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fabric.with(this, new Crashlytics());
setContentView(R.layout.activity_user_data_screen);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setSupportActionBar((Toolbar) findViewById(R.id.tool_bar));
context = getApplicationContext();
initNumberPicker();
initVar();
presenter = new PresenterActivityUserDataScreen(this);
}
private void initNumberPicker() {
NumberPicker pickerHeight = (NumberPicker) findViewById(R.id.pickerHeight);
UtilClass.setDividerColor(pickerHeight, UtilClass.getMyColor(context, R.color.ntz_color_yellow));
pickerHeight.setOnValueChangedListener(changeListener);
pickerHeight.setMaxValue(220);
pickerHeight.setMinValue(130);
pickerHeight.setValue(States.HEIGHT_DEFAULT);
NumberPicker pickerWeight = (NumberPicker) findViewById(R.id.pickerWeight);
UtilClass.setDividerColor(pickerWeight, UtilClass.getMyColor(context, R.color.ntz_color_yellow));
pickerWeight.setOnValueChangedListener(changeListener);
pickerWeight.setMaxValue(120);
pickerWeight.setMinValue(35);
pickerWeight.setValue(States.WEIGHT_DEFAULT);
}
private void initVar() {
tilUserName = (TextInputLayout) findViewById(R.id.tilUserName);
SwitchButton switchButton = (SwitchButton) findViewById(R.id.sb_custom);
switchButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
gender = WOMEN;
}else {
gender = MEN;
}
}
});
EditText etAvatarName = (EditText) findViewById(R.id.etAvatarName);
etAvatarName.setText(getResources().getString(R.string.avatar));
}
private NumberPicker.OnValueChangeListener changeListener = new NumberPicker.OnValueChangeListener() {
#Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
switch (picker.getId()) {
case R.id.pickerHeight:
inputHeight = newVal;
break;
case R.id.pickerWeight:
inputWeight = newVal;
break;
}
}
};
#Override
public final void onBackPressed() {
UtilClass.processClick(context);
if (backPressedQ == 1) {
backPressedQ = 0;
super.onBackPressed();
overridePendingTransition(R.anim.open_main, R.anim.close_next);
} else {
backPressedQ++;
Toast.makeText(this, "Press again to exit", Toast.LENGTH_SHORT).show();
}
//Обнуление счётчика через 5 секунд
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
backPressedQ = 0;
}
}, 5000);
}
public final void goNext(View view) {
UtilClass.processClick(context);
EditText editText = tilUserName.getEditText();
Editable editable = null;
if (editText != null) {
editable = editText.getText();
}
if (editable != null) {
avatarName = editable.toString();
}
if (!isValidAvatarName()) return;
saveUserData();
MetadataSaver saver = new MetadataSaver(context);
saver.saveFirstUserInfo();
saver.saveDeviceInfo();
PreferencesHelper.savePref(context, States.STILL_NOT_FINISH, true);
UtilClass.goToNextActivity(ActivityUserDataScreen.this, ActivityVideo.class);
}
private void saveUserData(){
saveAvatarGender();
saveAvatarHeight();
saveAvatarWeight();
saveAvatarName();
}
private void saveAvatarGender(){
if (gender == null){
gender = MEN;
}
PreferencesHelper.savePref(context, States.AVATAR_GENDER, gender);
}
private boolean isValidAvatarName() {
if (UtilClass.isTextEmpty(avatarName)) {
tilUserName.setErrorEnabled(true);
tilUserName.setError(getResources().getString(R.string.fill_your_avatar_name));
return false;
}
if (avatarName.contains(" ")) {
avatarName = avatarName.replace(" ", "");
}
if (!UtilClass.isLatinAlphabet(avatarName)) {
tilUserName.setErrorEnabled(true);
tilUserName.setError(getResources().getString(R.string.avatar_name_in_english));
return false;
}
if (!UtilClass.isNameFree(context, avatarName)) {
tilUserName.setErrorEnabled(true);
tilUserName.setError(getResources().getString(R.string.avatar_name_already_in_use));
return false;
}
return true;
}
private void saveAvatarHeight() {
int result;
if (inputHeight == 0) {
result = States.HEIGHT_DEFAULT;
} else {
result = inputHeight;
}
PreferencesHelper.savePref(context, States.AVATAR_HEIGHT, result);
}
private void saveAvatarWeight() {
int result;
if (inputWeight == 0) {
result = States.WEIGHT_DEFAULT;
} else {
result = inputWeight;
}
PreferencesHelper.savePref(context, States.AVATAR_WEIGHT, result);
}
private void saveAvatarName() {
PreferencesHelper.savePref(context, States.AVATAR_NAME, avatarName);
}
public final void switchManWoman(View view) {
UtilClass.processClick(context);
}
}
Thanks in advance!
The things to take into account are:
The view needs to be as dumb as possible. Think of it as an executor of the commands given by the presenter, and reporter to the presenter of all the stuff that happened on the UI. The interface should provide methods like "display this text", and / or calling presenter's methods like "the button was clicked".
the presenter is the one in command. It drives your view behaviour and reacts to the inputs coming from the view itself. Ideally, it should abstract from anything Android related, in this way you can test the behaviour inside vanilla tests.
Google has published a collection of samples to discuss and showcase different architectural tools and patterns for Android apps.
To begin, very usefull to you to understand how this one works. And adapt to your sample.
[...] This sample is the base for many of the variants. It showcases a simple implementation of the Model-View-Presenter pattern with no architectural frameworks. It uses manual dependency injection to provide a repository with local and remote data sources. Asynchronous tasks are handled with callbacks [...]
I highly recommend reading this article on medium: https://medium.com/#tinmegali/model-view-presenter-mvp-in-android-part-1-441bfd7998fe#.f4yiylrwa .
In essence, all things related to the android SDK should be put in your "view" (and occasionally your model), which will usually be a fragment or activity. Figuring out the difference between your model and presenter will be more up to you, however, you can think about your presenter as the thing that makes program logic decisions based on inputs to your application. Often, the mvp pattern is used in Android development to try to get around rotation and activity recreation issues so you may have luck using a static presenter for a small sample application.
Best of luck!

Accessing widget from android application

I am trying to add weather widget into my application. I used this code to find target weather widget:
public class widgetTask extends AsyncTask<Context, Void, AppWidgetHostView> {
final static int APPWIDGET_HOST_ID = 1;
final static String WEATHER_PACKEGE = "accuweather.android";
final static String WEATHER_CLASS = "accuweather.android.widgets.AL_WidgetProvider";
#Override
protected AppWidgetHostView doInBackground(Context... arg0) {
AppWidgetHostView hostView = null;
AppWidgetManager AWmanager = AppWidgetManager.getInstance(arg0[0]);
AppWidgetHost AWHost = new AppWidgetHost(arg0[0], APPWIDGET_HOST_ID);
AppWidgetProviderInfo AWProviderInfo = new AppWidgetProviderInfo();
int AWId = AWHost.allocateAppWidgetId();
List<AppWidgetProviderInfo> AWProviderInfos = new ArrayList<AppWidgetProviderInfo>();
AWProviderInfos = AWmanager.getInstalledProviders();
for(int j = 0; j < AWProviderInfos.size(); j++)
{
if (AWProviderInfos.get(j).provider.getPackageName().equals("com."+WEATHER_PACKEGE) && AWProviderInfos.get(j).provider.getClassName().equals("com."+WEATHER_CLASS))
{
AWProviderInfo = AWProviderInfos.get(j);
break;
}
}
hostView = AWHost.createView(arg0[0], AWId, AWProviderInfo);
hostView.setAppWidget(AWId, AWProviderInfo);
return hostView;
}
}
After that I tried to add AppWidgetHostView into my Activity:
AppWidgetHostView weatherWidget = WT.execute(this).get();
LLWeather.addView(weatherWidget);
It worked but widget showed "Downloading weather data"(internet permissions granted to this activity) and freezed so I cant interact with it.
Any ideas how to fix it and access to widget functions?
Do not use get() on your asynctask call as it will not be async anymore. The result of doInBackground will be available in onPostExecute. In onPostExecute you call LLWeather.addView.

Android TTS fails to speak large amount of text

I am trying to speak out large amount of text using Android Text To Speech. I using default Google speech engine. Below is my code.
public class Talk extends Activity implements TextToSpeech.OnInitListener {
private ImageView playBtn;
private EditText textField;
private TextToSpeech tts;
private boolean isSpeaking = false;
private String finalText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_talk);
//Intialize the instance variables
playBtn = (ImageView)findViewById(R.id.playBtn);
textField = (EditText)findViewById(R.id.textField);
//Resister the listeners
playBtn.setOnClickListener(new PlayBtnAction());
//Other things
tts = new TextToSpeech(this,this);
//Get the web page text if called from Share-Via
if (Intent.ACTION_SEND.equals(getIntent().getAction()))
{
new GetWebText().execute("");
}
}
//This class will execute the text from web pages
private class GetWebText extends AsyncTask<String,Void,String>
{
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
String text = getIntent().getStringExtra(Intent.EXTRA_TEXT);
String websiteText = "";
try {
//Create a URL for the desired page
URL url = new URL(text);
// Read all the text returned by the server
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String str;
StringBuffer strBuffer = new StringBuffer("");
while ((str = in.readLine()) != null)
{
strBuffer.append(str+"\n"+"\n");
}
in.close();
String html = strBuffer.toString();
Document doc = Jsoup.parse(html);
websiteText = doc.body().text(); // "An example link"
//Toast.makeText(this, websiteText, Toast.LENGTH_LONG).show();
}
catch(Exception e)
{
Log.e("web_error", "Error in getting web text",e);
}
return websiteText;
}
#Override
protected void onPostExecute(String result)
{
textField.setText(result);
}
}
}
//Class to speak the text
private class PlayBtnAction implements OnClickListener
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
if(!isSpeaking)
{
isSpeaking = true;
//speak(textField.getText().toString());
finalText = textField.getText().toString();
new SpeakTheText().execute(finalText);
isSpeaking = false;
}
else
{
isSpeaking = false;
tts.stop();
}
}
}
#Override
public void onInit(int status) {
// TODO Auto-generated method stub
if(status==TextToSpeech.SUCCESS)
{
int result = tts.setLanguage(Locale.UK);
if(result==TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED)
{
Toast.makeText(this, "Language Not Supported", Toast.LENGTH_LONG).show();
}
}
}
//This class will speak the text
private class SpeakTheText extends AsyncTask<String,Void,String>
{
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
tts.speak(params[0], TextToSpeech.QUEUE_FLUSH, null);
return null;
}
}
#Override
public void onDestroy()
{
if(tts!=null)
{
tts.stop();
tts.shutdown();
}
super.onDestroy();
}
}
But the issue here is, when there is a large chunk of text (lets say you have extracted text from a web page) the TTS fails to read it. If I remove most of the text, then it will read it. Why is this happening?
When I am about to read the large text, the LogCat however display something like this
10-11 07:26:05.566: D/dalvikvm(2638): GC_CONCURRENT freed 362K, 44% free 3597K/6312K, paused 17ms+8ms, total 93ms
The String length should not be longer than pre-defined length, from docs:
Parameters
text The string of text to be spoken. No longer than getMaxSpeechInputLength() characters.
Returned value by getMaxSpeechInputLength() may vary from device to device, but according to AOSP source that is whopping 4000:
/**
* Limit of length of input string passed to speak and synthesizeToFile.
*
* #see #speak
* #see #synthesizeToFile
*/
public static int getMaxSpeechInputLength() {
return 4000;
}
Try not to exceed that limit: compare input text length with that value and split into separate parts if necessary.
Use this code...Working for any file ..
just send the string to speech function..
private void speech(String charSequence) {
int position ;
int sizeOfChar= charSequence.length();
String testStri= charSequence.substring(position,sizeOfChar);
int next = 20;
int pos =0;
while(true) {
String temp="";
Log.e("in loop", "" + pos);
try {
temp = testStri.substring(pos, next);
HashMap<String, String> params = new HashMap<String, String>();
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, temp);
engine.speak(temp, TextToSpeech.QUEUE_ADD, params);
pos = pos + 20;
next = next + 20;
} catch (Exception e) {
temp = testStri.substring(pos, testStri.length());
engine.speak(temp, TextToSpeech.QUEUE_ADD, null);
break;
}
}
}
In case someone might find this helpful. When you split the large text into strings, do not set the length of each string to the exact value of getMaxSpeechInputLength(). Subtract the string length by 1. Otherwise, only the last chunk of string could be read by TTS.
int length = toSpeech.getMaxSpeechInputLength() - 1;
Iterable<String> chunks = Splitter.fixedLength(length).split(largeText);
Lists.newArrayList(chunks);
It is worse than the 4000 characters limit in practice on Android. There are some TTS engines that limit the input length a lot more. For example Nuance.tts and vocalizer.tts engines won't speak any string longer than about 512 characters (from my tests some time ago). Today I hit a limit of below 300 characters in es.codefactory.eloquencetts package, which simply crashes if the string I send to it is more than 256-300 characters. I divide the contents into sentences, and guard for sentences longer than the above limit, further sub-dividing them in my app code.
Greg
If you follow ozbek's advice you should be fine. I too have large text files that I want spoken. I simply used the streamreader method and everything works fine. heres' PART of my code. it's the part that you should use. My code does a bit more than you want but it works for me and may work for you.
Dim sReader As StreamReader = New StreamReader(Story_file)
Try
Do Until EndOfStream '= True
Dim line_to_speak As String = sReader.ReadLine
Dim vc = Mid(line_to_speak, 1, 1) <- you dont need this
Select Case vc <- you dont need this
Case Is = "/" <- you dont need this
voice_index = Val(Mid(line_to_speak, 2, 2)) <- you dont need this
srate = Val(Mid(line_to_speak, 5, 2)) <- you dont need this
edassistv.lstVoices.SelectedIndex = voice_index <- you dont need this
selected_voice = edassistv.lstVoices.SelectedItem <- you dont need this
Case Else<- you dont need this
synth.SelectVoice(selected_voice)
synth.Speak(line_to_speak)
End Select<- you dont need this
Loop
Catch ex As Exception
GoTo finish

Categories