Getting the first result on Google Speech recognition - android

In the Android dev guide there is an example on how to implement the speech recognition. That example prints a list of results using an array.
What if I'm only interested in the first result?
I have implemented it this way (data is the Intent returned by the Activity result):
data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS).get(0)
Is there another way to get just the first result without getting an array? Something like a getFirst method?

No, the api does not specify some kind of getFirst method.
If you use this in different places, you can create one for yourself, which does a null check and returns the first result:
public String getFirst(Intent data){
List<String> results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
if(results != null && results.size() > 0){
return results.get(0);
}
return null; //or maybe: return "";
}

The object returned from getStringArrayListExtra() is a ArrayList, which does not offer a getFirst() call. You could call iterator() and get the first entry on that via next(), but get(0) will probably be more efficient, because it is a plain array access in contrast to an object creation.

Related

How to use a flatmap rxJava to perform concurrent task

I want to call a function twice with different parameters and the function returns set of values based on parameters. I want to collate both results and do something with it.
I looked up and I should be using flatmap to do that, but I am not sure how to.can you guide me on it please.
getCompaniesData(pageNumber, perPage) // returns 100 companies
getCompaniesData(pageNumber, perPage) //returns 100 companies
Collate both responses - total 200 companies
Do something with it.
Currently this is what I have which returns with params (1,100), Once I get the data I want to call the same function with params (2,100) which gives me another set of data and combine them both and do something with them
mHighLightsPresenter. getCompaniesData(1, 1000).doOnNext(fetchCompaniesResponse -> {
if(fetchCompaniesResponse != null)
{
List<com.dopay.onboarding.data.bean.Company> companies = fetchCompaniesResponse.getCompanies();
if (companies != null && !companies.isEmpty()) {
showCompaniesDialog(companies);
}
Toast.makeText(getContext(), "companies response is not null", Toast.LENGTH_LONG).show();
}
}).subscribe();
Your suggestions are very helpful
Thanks
R
Check first the docs of the flatMapoperator, it says:
transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable.
How can I call the same function with different params?
You can extract the method getCompaniesData and pass to it two integers (or a proper class), in this way:
Observable<T> getCompaniesData(Param param);
How can I combine the different results?
You can apply the operator flatMap to the multiple Observables emitted by the defined method.
Observable<T> foo(Param... params) {
return Observable.fromArray(params)
.flatMap(this::getCompaniesData)
...
}

ArrayList Remove Object

I'm working on an app in android studio. The part of the app I'm having issues with is where the user can favourite and remove their favourite item. I do this by adding and removing the item from a list.
The thing is the add functionality works which is:
public void addFavorite(Context context, NewSubject subject) {
List<NewSubject> favorites = getFavorites(context);
if (favorites == null)
favorites = new ArrayList<NewSubject>();
favorites.add(subject);
saveFavorites(context, favorites);
}
I am passing in an object of type "NewSubject" which is just a class of getters and setters for name and id.
The problem arises when I try to remove an item from this list. Code below:
public void removeFavorite(Context context, NewSubject subject) {
ArrayList<NewSubject> favorites = getFavorites(context);
if (favorites != null) {
favorites.remove(subject);
saveFavorites(context, favorites);
}
}
I've even tried something like:
for(int i = 0; i < favorites.size(); i++){
if(favorites.get(i).getSubject_name() == subject.getSubject_name())
favorites.remove(i);
}
Even though both subject names match, the if statement never triggers as true. By changing it to ID it does remove the item but I was wondering why it doesn't work the other way. MeetTitan suggested to use "equals" operator to compare Strings and this has fixed that issue. But I'm still wondering as to why removing the item by "subject" without the FOR loop and IF statement doesn't work.
I have cleared the app's data multiple times whilst trying to debug the source of the problem.
Thank you for your time and help, it is much appreciated.
This applies if you are re-creating NewSubject twice... If you are trying to remove the exact same instance of NewSubject that you got from the collection, then I guessed wrong and this isn't the answer you are looking for.
Is it possible you haven't defined equals and hashCode in your Favorites object? Without those remove will only work with the EXACT same object instance in the collection. If you haven't, try defining them and see if remove() works the way you expect.
Without those methods defined, collections will respond this way:
Obj x=new Obj("data")
Obj y=new Obj("data")
collection.put(x)
collection.remove(y)
assert( collection.size() == 1) // was not removed because .equals didn't exist--remove reverted to == instead which failed, x != y
collection.remove(x)
assert( collection.size() == 0) // NOW it worked because you used the same instance.
if you define .equals and hashCode to compare the strings inside obj, then this will work:
collection.put(x)
collection.remove(y)
assert( collection.size() == 0) // worked because x.equals(y)!
Try
String.equalsIgnoreCase(value1,value2)
This might do your work.
From your example, it's evident that name is a String object. In java, you have to use ".equals()" or comparing two strings.
You can do this:
if(favorites.get(i).getSubject_name().equals(subject.getSubject_name())){
...
}
Or, you can override the equals() method in your NewSubject class to make this work:
favorites.remove(subject);
You can use something like this as your equals() method in the NewSubject class (considering you are only matching two NewSubject objects based on their names):
#Override
public boolean equals(Object other){
if (other == null) return false;
if (other == this) return true;
NewSubject otherSubject = (NewSubject) other;
if(this.getSubject_name().equals(otherSubject.getSubject_name()))
return true;
else
return false;
}
Update:
You may want to override hashcode() as well. If your NewSubject class ever gets used in a hash-based collection such as HashMap, overriding only equals() method will not be sufficient. For reference, this is from Effective Java by Joshua Bloch:
You must override hashCode() in every class that overrides equals().
Failure to do so will result in a violation of the general contract
for Object.hashCode(), which will prevent your class from functioning
properly in conjunction with all hash-based collections, including
HashMap, HashSet, and Hashtable.

How to fetch object and array fields with Parse?

I'm unable to properly fetch a ParseObject that contains a field of type 'Object' : after changing manually the 'Object' field value in the Parse DataBrowser and then fetch the ParseObject from the app, the fetched ParseObject still provide the old value for the 'Object' field, but provide the right new value for the 'String' field.
Here is the sample code I use :
public class MainActivity extends ActionBarActivity {
ParseObject object;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
object = ParseObject.createWithoutData("Test", "tvgTg8jAXz");
}
#Override
protected void onResume() {
super.onResume();
object.fetchInBackground().onSuccess(new Continuation<ParseObject, Object>() {
#Override
public Object then(Task<ParseObject> task) throws Exception {
JSONObject data = task.getResult().getJSONObject("data");
String name = task.getResult().getString("name");
Log.d("OBJECT", data.toString());
Log.d("OBJECT", name);
return null;
}
}).continueWith(new Continuation<Object, Object>() {
#Override
public Object then(Task<Object> task) throws Exception {
if (task.getError() != null) {
Log.e("OBJECT", task.getError().getLocalizedMessage());
}
return null;
}
});
}
}
After I change both 'data' and 'name' fields in the DataBrowser, if 'onResume()' is called without a previous call to 'onCreate()' (after locking/unlocking screen for example) then the logs shows the old value for 'data' and the new value for 'name'.
This is a simple code example to highlight the problem I encounter in a bigger project.
Is this a known issue of the Parse Android SDK ? Is there a workaround ?
Thanks
Now that I learned that you have turned on the local datastore I can come with an, at least partial, answer.
Turning on the local datastore has some side effects. One being that only one instance of each object exists locally. So when you call fetchInBackground the second time, object is already populated with data. The problem then (i think) is that the API no longer override 'complex' types (pointers, objects, arrays), perhaps because it could mess up internal relationships in the data store. Since the fact that the data store will recursively save an object (and pointers) so suddenly swapping a pointer might leave objects 'hanging'. (again, only guessing).
Now I must admit that it still confuses me a bit looking at your code, cause it does not seem that you at any point write your object to the data store, however..
What should work is to unpin the object before 'refreshing' it:
object.unpinInBackground.onSuccess(new Continuation<>{
...
// when done call fetch
});
According to Parse, this is a known issue that they will not fix for now : https://developers.facebook.com/bugs/1624269784474093/
We must use the following methods to retrieve JSON objects/arrays fields from a ParseObject :
getMap() instead of getJSONObject()
getList() instead of getJSONArray()
These methods will return Map and List objects respectively.
I found that managing Map and List in my project instead of JSONObjet and JSONArray is not a problem and is even clearer.

Android: Null safe equals before API v19

I have two objects Object1 and Object2, which may or may not be null.
I want to test null safe equality between them (true if both null, or both equal)
I have done my research and found Objects.equals(Object1,Object2), which fulfills its purpose.
But the problem is that it's only for API level 19+.
How do I make this compatible with lesser APIs?
There are several options.
You could override the
equals() method in the class you are comparing, and use obj1.equals(obj2)
You could use the hashCode() method of Object to determine if they are equivalent, by using obj1.hashCode() == obj2.hashCode()
Just using plain old == determines weather two variables contain the same instance of a class.
If these aren't null safe, you can easily write your own null checking with obj == null
This should be completely independent of the Android Api.
Have you tried Guava?
Guava has some pretty nice functionality that removes alot of the boilerplate.
Here is a link of their example.
Here is a simple comparison method. It seems odd that you have to roll your own, though.
/**
* Null safe comparison of two objects.
* #return true if the objects are identical.
*/
public static boolean objectEquals(Object o1, Object o2) {
if (o1 == null && o2 == null) return true;
if (o1 == null) return false;
return o1.equals(o2);
}

Passing multiple data to an Activity?

I'm trying to pass multiple data items in one Intent:
if (strActStat == "Sedentary") {
// passactStat.putString("keySedentary", strActStat);
// passSeden.putString("keyMale", gender);
i = new Intent(CalorieTrackerTargetWeight.this, TargetWeightResults.class);
i.putExtra("keyGender", gender);
i.putExtra("keyAct", strActStat);
//i.putExtra("keyAct", strActStat);
startActivity(i);
}
Why doesn't this work? Why can't I pass multiple items in one Intent?
You can't compare strings with ==.
if (strActStat.equals("Sedentary")) { // should work
Edit:
#Hesam has written a pretty detailed answer but his solution is not really usable. Instead of using an ArrayList<String> you should stick with the putExtra(key, value). Why? Well there are some advantages over the ArrayList solution:
you are not limited to the type of the ArrayList
you are not forced to keep a static order in you list. As you can only work with index values to get a list you need to make sure that the put() was in the same order as get(). Think of the following case: You you often send 3 values, but in some cases you don't want to send the second value. When you use the ArrayList solution, you end up sending null as the second value to ensure that the third value will stay in his place. This is highly confusing coding! Instead you should just send two values and when the receiving activity tries to receive the second value, it can handle the returning null like it want... for example replace it with a default value.
Naming of the key will grant you the knowledge of always knowing what should be inside...
Your key should be declared in the receiving Activity as a constant. So you always know by looking at this constants what intent data the activity can handle. This is good programming!
Hope this helps in clarifying the intent usage a bit.
I think this is not the only problem, first, if (strActStat == "Sedentary") this is wrong. you can't compare to string in this way. Because in this way objects are comparing not the string. Correct way is if (strActStat.equalIgnoreCase("Sedentary")).
If you use Parcelable then you can pass multiple data in just 1 intent.
Also you can use ArrayList<String>.
Here is a skeleton of the code you need:
Declare List
private List<String> test;
Init List at appropriate place
test = new ArrayList<String>();
and add data as appropriate to test.
Pass to intent as follows:
Intent intent = getIntent();
intent.putStringArrayListExtra("test", (ArrayList<String>) test);
Retrieve data as follows:
ArrayList<String> test = data.getStringArrayListExtra("test");
Hope that helps.
Try this:
done.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
namevalue=name.getText().toString();
overvalue=over.getText().toString();
audiostatus=audio.getText().toString();
Intent intent=new Intent(Settings.this,home.class);
Bundle bundle = new Bundle();
bundle.putString( "namevalue",namevalue);
bundle.putString("overvalue",overvaluse);
bundle.putInt("value",variablename);
intent.putExtras(bundle);
startActivity(intent);
}
});
I faced the same problem.
My mistake was that one of the variable I was transferring was not initialized.
Like gender or strActStat in your case.

Categories

Resources