The thing that bugs me the most about this is; I have another activity that uses a different approach (using startActivityForResult(intent....) vs a listener class implementing RecognitionListener, and one works the other doesnt'. I'm certain I'm doing something stupidly wrong, but I sure can't figure out what.
I'm getting the speech recog results back using onResults, using a listener class that implements RecognitionListener.
public void onResults(Bundle results) {
Log.d("Speech", "onResults");
ArrayList strlist = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
for (int i = 0; i < strlist.size(); i++) {
String matchstring = matchpair[1].toString().toLowerCase();
String speechstring = strlist.get(i).toString().toLowerCase();
Log.d("Speech", "result=" + speechstring);
if (checkResult(matchstring, speechstring)) {
System.out.println("Phonetic match: " + speechstring + " = " + matchstring);
} else System.out.println("NO match: " + speechstring + " = " + matchstring);
}
}
The checkresult is simple, just a boolean compare:
public boolean checkResult(String result, String checkmatch) {
if (result.equals(checkmatch))
{
return true;
}
return false;
}
Looking at the debug info, the results appear to compare - but the boolean is returning false.
It's driving me nuts. I'm going this route so I can use the recognition functionality without having the Google dialog pop on every recognition attempt. In the activity I began with, the compare is working perfectly.
I welcome someone pointing out whatever very stupid thing I am overlooking.
Related
I need to create WiFi scanner app on android device. I managed to do it, yet there is something I don't know how to deal with.
class WifiReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
sb = new StringBuilder();
Comparator<ScanResult> comparator = new Comparator<ScanResult>() {
#Override
public int compare(ScanResult o1, ScanResult o2) {
return (o1.level>o2.level ? -1 : (o1.level==o2.level ? 0 : 1));
}
};
lista = wifiManager.getScanResults();
Collections.sort(list, comparator);
for (int i = 0; i < list.size(); i++) {
scanResult = wifiManager.getScanResults().get(i);
sb.append(new Integer(i + 1).toString() + ". " + (list.get(i)).SSID + " " + (list.get(i)).BSSID + " " + (list.get(i)).level + "\n");
}
txt.setText(sb);
wifiManager.startScan();
}
}
There are several WiFi networks in the building with the same SSID, lets say ABCD. I want to save in list, which is List<ScanResult> type, only networks with this specific SSID ABCD without the need to create another field such as list if possible. I woukd be grateful for any help
I assume you mean you want a way to filter the scan and return only the specified ssid, there is no way that I know of on the back-end to do that. You can go through your existing list and pull out the ones you want and save to a new List.
You can also use your existing code and check to see if the ssid matches inside your loop and only build the string if it does.
Most of the time you will be showing a list of available networks in a list or recycler view so usually the secondary list is the way to go.
I want to test an application but it's too large to do by static approach.
I started googling. I found a interesting tool called Xposed Framework.
I read a lot of documents / examples. But I cant find the theads about getting method name of application.
My purpose is to log current method name when I press a button in app. Which parameters are sent when the methods are called?
For more information, the application I want to test is a chat application. I want to check that is it secured to use ? Is it true that developers claims the application uses blah blah blah encryption ? Is it real end-to-end encryption?.
According to the large of application, I need some tools to help me analyse this. When I send a message what methods are called ? what values are sent along with ?
If it is opensource you can easily insert a few logs in the source code and recompile. Some code coverage tools allow you to log the executed methods but i am unsure about the parameters (e.g. EMMA coverage).
If it is closed-source then you can do it with Xposed, but it has some challenges. Xposed allows you to hook Java methods, if it is opensource you can lookup the specific methods you want to intercept and print their parameters. If it is closed source, you can always check the method names through decompiling the app with apktool.
Check the Xposed tutorial on how to register hooks. Assuming you created your class that extends XC_MethodHook, the following methods should do the trick for primitive parameters:
#Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
String threadname = Thread.currentThread().getName();
String d = _dateFormat.format(new Date());
Class<?> cls = param.this.getClass();
//Extend XC_MethodHook to receive the mthName in the constructor
//and store it as a static field.
Log.v("MethodInvocation", "[A][" + d + "]"
+ "[" + cls.getName() + "."
+ mthName
+ "(" + args(param) + ")" + " = " + result(param)
+ "]" + " [" + threadname + "]");
}
public boolean shouldPrintContent(Object o) {
if (o.getClass().isPrimitive()
|| o.getClass().getName().contains("java.lang"))
return true;
return false;
}
public String args(MethodHookParam param) {
String args = "";
int counter = 0;
if (param != null) {
for (Object o : param.args) {
if (counter > 0)
args += ",";
// argument can be null
if (o == null) {
args += "null";
} else { // if it is an object lets print its type and content.
args += printclean(o.getClass().getName());
if (shouldPrintContent(o)) {
args += ":" + printclean(o.toString());
} else
args += ":nonPrimitiveOrJavaLang";
}
counter++;
}
}
return args;
}
//avoid identation chars in strings
public String printclean(String str) {
char[] res = str.toCharArray();
for (int i = 0; i < str.length(); i++) {
if (res[i] == '\n' || res[i] == '\r' || res[i] == '\t'
|| res[i] == '[' || res[i] == ']') {
res[i] = '*';
}
}
return String.valueOf(res);
}
public String result(MethodHookParam param) {
String res = "";
Object retobj = param.getResult();
if (retobj == null) {
res += "null";
} else {
res += printclean(retobj.getClass().getName());
if (shouldPrintContent(retobj)) {
res += printclean(retobj.toString());
} else
res += "(nonPrimitiveOrJavaLang)";
}
return res;
}
Note that printing any object is not trivial. Here I printed only known types like primitives or other java.lang objects. More complex objects (including collections) you can try using Gson to represent them but this also comes with limitations (e.g. can't often handle reference loops).
Finally, be careful with what method you hook as hooking and logging methods that are called often will impact the performance of the app.
Good luck!
A new Xposed module called Inspeckage does (among many other useful inspections) what you want to do: you can use it to hook any method and view and even change its input and output.
I have an app for people with low vision that relies heavily on TTS. However for some reason when I use the speak method TTS randomly skips the first few letters of a sentence or speaks the first few letters in a ver low volume and the rest in a normal volume.
Any idea why this might happen?
This is my current code:
public class SpeechHelper implements TextToSpeech.OnInitListener {
private Context context = null;
private TextToSpeech tts;
public SpeechHelper(Context context)
{
this.context = context;
try {
tts = new TextToSpeech(context, this);
} catch(Exception e) {
Log.e("Phone Features Exception","Couldn't initiate TTS", e);
}
}
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.getDefault());
}
}
public void speak(String s, int mode, String messageID) {
Log.d("VOLUME", "getStreamVolume " + am.getStreamVolume(AudioManager.STREAM_MUSIC)); // Always 15
Log.d("VOLUME", "isMusicActive " + (am.isMusicActive() ? "true" : "false")); // Always false
Log.d("VOLUME", "isVolumeFixed " + (am.isVolumeFixed() ? "true" : "false")); // Always false
Log.d("VOLUME", "isSpeakerphoneOn: " + (am.isSpeakerphoneOn() ? "true" : "false")); // Always false
Log.d("VOLUME", "getMode: " + am.getMode()); // Always 0
HashMap<String, String> params = new HashMap<String, String>();
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, messageID);
tts.speak(s, mode, params);
}
}
I've noticed the problem always happens on the next 5 seconds after making a call or when unlocking the phone to the app.
Either you are doing something wrong or Android is doing something wrong. If I had to put money on it I would say it is you.
Start by just calling
tts.speak("the quick brown fox jumps over the lazy dog", tts.QUEUE_FLUSH, null);
to see if you can reproduce the problem in a test app (I couldn't). If you can, then I'd be very curious as to what phone/OS you are running on . Your problem probably lies with truncated strings, or something else programmatically messing with volume.
The first time the Asynctask executes takes 30 or more seconds. It happens when I enter the activity. After that, subsequents call to the Asyntask(when I enter the activity again from the previous activity) takes only 4 or 5 seconds, which I consider to be "acceptable".
Here is the code where I execute the AsyncTask
#Override
public void onLocationChanged(Location location) {
if (location!=null) {
mlastLocation=location;
double latitud=Double.parseDouble(getIntent().getStringExtra("latitud").replace("Latitud:", ""));
double longitud=Double.parseDouble(getIntent().getStringExtra("longitud").replace("Longitud:", ""));
LatLng origen= new LatLng(latitud,longitud);
LatLng destino=new LatLng(mlastLocation.getLatitude(),mlastLocation.getLongitude());
if (mCount==0) {
FillVariablesAsyncTask tareaAsincrona = new FillVariablesAsyncTask();
tareaAsincrona.execute(origen, destino);
mCount++;
}
}
}
And here the code of the AsyncTask, where onPostExecute updates members variables and update the UI.
private class FillVariablesAsyncTask extends AsyncTask<LatLng,Void,Document>{
#Override
protected Document doInBackground(LatLng... params) {
md=new GMapV2Direction();
LatLng origen=new LatLng(params[0].latitude,params[0].longitude);
LatLng destino=new LatLng(params[1].latitude,params[1].longitude);
Document doc = md.getDocument(origen, destino, GMapV2Direction.MODE_WALKING);
/*mUbicacionActual = md.getStartAddress(doc);
mDuration=md.getDurationText(doc);
mDistancia=md.getDistanceText(doc);*/
return doc;
}
#Override
protected void onPostExecute(Document doc) {
super.onPostExecute(doc);
mUbicacionActual = md.getStartAddress(doc);
mDuration=md.getDurationText(doc);
mDistancia=md.getDistanceText(doc);
if (mUbicacionActual!=null && mDistancia!=null && mDuration!=null) {
progressBar.setVisibility(View.GONE);
btnIr.setEnabled(true);
tvOrigenLatitud.setText("Latitud:"+String.valueOf(mlastLocation.getLatitude()));
tvOrigenLongitud.setText("Longitud"+String.valueOf(mlastLocation.getLongitude()));
tvDestino.setText("Destino:" + getIntent().getStringExtra("info").replace("Info:", ""));
tvDestinoLatitud.setText("Latitud:" + getIntent().getStringExtra("latitud").replace("Latitud:", ""));
tvDestinoLongitud.setText("Longitud:" + getIntent().getStringExtra("longitud").replace("Longitud:", ""));
tvOrigen.setText("Origen:" + mUbicacionActual);
tvDistancia.setText("Distancia:"+mDistancia);
tvTiempo.setText("Tiempo:" + mDuration);
}
}
}
I've tried out .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) but the app crashes. I've tried out also with a handler but it shows the same Behaviour, the first time takes 30 seconds or so, while the subsequents takes only a few.
Edit to show to points where i added log:
if (mCount==0) {
FillVariablesAsyncTask tareaAsincrona = new FillVariablesAsyncTask();
mStart=System.currentTimeMillis();
Log.i("START_BEFORE_EXECUTE", mStart + "");
tareaAsincrona.execute(origen, destino);
long end=System.currentTimeMillis();
Log.i("ELAPSED_EXECUTE", ((end-mStart)/1000) + "");
mCount++;
}
Here :
protected Document doInBackground(LatLng... params) {
long end;
end =System.currentTimeMillis();
Log.i("ELAPSE_PRE_BACKGROUND",((end- mStart)/1000)+"");
md=new GMapV2Direction();
end=System.currentTimeMillis();
Log.i("ELAPSED_POS_GMAPV2DIR",((end- mStart)/1000)+"");
LatLng origen=new LatLng(params[0].latitude,params[0].longitude);
LatLng destino=new LatLng(params[1].latitude,params[1].longitude);
end=System.currentTimeMillis();
Log.i("ELAPSED_PRE_GETDOCUMENT",((end- mStart)/1000)+"");
Document doc = md.getDocument(origen, destino, GMapV2Direction.MODE_WALKING);
end=System.currentTimeMillis();
Log.i("ELAPSED_POS_BACKGROUND",((end- mStart)/1000)+"");
/*mUbicacionActual = md.getStartAddress(doc);
mDuration=md.getDurationText(doc);
mDistancia=md.getDistanceText(doc);*/
return doc;
}
and here:
long end=System.currentTimeMillis();
Log.i("ELAPSED_onPostExecute",((end-mStart)/1000)+"");
mUbicacionActual = md.getStartAddress(doc);
mDuration=md.getDurationText(doc);
mDistancia=md.getDistanceText(doc);
end=System.currentTimeMillis();
Log.i("ELAPSED_POST_FILLVARS",((end-mStart)/1000)+"");
if (mUbicacionActual!=null && mDistancia!=null && mDuration!=null) {
progressBar.setVisibility(View.GONE);
btnIr.setEnabled(true);
tvOrigenLatitud.setText("Latitud:" + String.valueOf(mlastLocation.getLatitude()));
tvOrigenLongitud.setText("Longitud" + String.valueOf(mlastLocation.getLongitude()));
tvDestino.setText("Destino:" + getIntent().getStringExtra("info").replace("Info:", ""));
tvDestinoLatitud.setText("Latitud:" + getIntent().getStringExtra("latitud").replace("Latitud:", ""));
tvDestinoLongitud.setText("Longitud:" + getIntent().getStringExtra("longitud").replace("Longitud:", ""));
tvOrigen.setText("Origen:" + mUbicacionActual);
tvDistancia.setText("Distancia:"+mDistancia);
tvTiempo.setText("Tiempo:" + mDuration);
end=System.currentTimeMillis();
Log.i("ELAPSED_POS_onPostExecute", ((end - mStart) / 1000) + "");
}
this image shows the log output, it shows 3 but in reality is 30 or more.
[IMG]http://i61.tinypic.com/95o1ef.png[/IMG]
The time is taking have absolutely nothing to do with AsyncTask or Thread or Handler or Executor
The issue is that library you're using really takes that long to make calls to a server, or to process the information and I don't believe there's much you can do about it. It's only the 1st time because I'm guessing the library caches the result, but it still have nothing to do with the threading model you use.
The main point of my answer is that you're asking the wrong question. The correct question is:
Why this library is taking that long to process and what can you do to shorten it?
Unfortunately the only possible way to answer it is by analysing the source code of it or talking directly with the library developer.
edit:
to help you measure the executions:
public static class TimeMeasure {
private final DecimalFormat format;
private final double start;
private final String tag;
public TimeMeasure(String tag) {
this.format = new DecimalFormat("0.0");
this.start = System.currentTimeMillis();
this.tag = tag;
log("start);
}
public void log(String message) {
double elapsed = ((double) (System.currentTimeMillis() - start)) / 1000.0;
Log.d(tag, format.format(elapsed) + ": " + message);
}
}
then during doInBackground
protected Document doInBackground(LatLng... params) {
TimeMeasure tm = new TimeMeasure("Carlos");
// execute something:
tm.log("action 1");
// execute next
tm.log("action 2);
// etc...
}
I can't comment yet so here you go: you can use your IDE's debugger after you place breakpoints on every line in the two given blocks of code to see which line takes the most to execute. Then post your findings.
As the above answer mentioned it is actually the library that takes too much time.
I had a similar problem a while ago, I remember that after debugging what causes the problem was distance and duration and also if you were getting some kind of an address, it will contribute to the delay
(For Example) getting street name, city name and country etc..
I didn't really find any better API or library to deal with this but what i did was something to improve the user experience:
1-start another AsyncTask from onPostExecute() that will get duration and distance.
2- while the app is getting duration and distance don't block the user interface with a progress dialog or progress bar, just put loading... as an default value of your TextView then when the app receives the data setText to the actual value.
3-Do all of you data manipulation later after setting important data.
Hope this will help.
My problem is that I had a program working before, without threading, and it took a long time to process info (16 seconds to get XML data and display it). Now I've gotten the whole threading and async thing down, but for some reason it is making my program SLOWER (in the emulator, device is not available right now), is there anything I've done that could have caused this, the UI thread is fine, but my async thread takes a minute and a half to execute. (when I had it in the UI thread used to take only 16 seconds, but froze the UI thread)
Here is the code for my thread, it sits inside of the main class:
private class TeamSearchTask extends AsyncTask<String,Void,String> {
CharSequence nfo;
String [] matches;
String [] data;
String teamNum;
ProgressDialog loading;
protected void onPreExecute()
{
//Show the 'loading' dialog
loading = new ProgressDialog(SapphireAlliance.this);
loading.setMessage("Loading, please wait...");
loading.show();
}
protected String doInBackground(String... teamNumber)
{
try
{
//Team information ------------------------------------------------------------------------------------
teamNum = teamNumber[0];
//Array of team data
data = APIconnection.getTeams(teamNum, "");
//Display basic team info
nfo = ("\nFormal Team Name:\n" + data[1] +
"\n\nLocation:\n" + data [3] + ", " + data[4] + ", " + data[5] +
"\n\nRookie Year:\n" + data[6] +
"\n\nRobot Name:\n" + data[7] +
"\n\nWebsite:\n" + data[8] + "\n\n\n\n\n\n\n\n\n");
//Make match archive --------------------------------------------------------------------------------------
String [] events = APIconnection.getEventIdsByYear(year1);
ArrayList<String> matches = new ArrayList<String>();
for (int i = 0; i<events.length; i++)
{
String [] add = APIconnection.getMatches2(teamNum, events[i] ,"","");
for(int j = 0; j<add.length; j++)
matches.add(add[j]);
}
String [] out = new String [matches.size()];
matches.toArray(out);
return "";
}
catch(Exception e)
{
return e.toString();
}
}
protected void onPostExecute(String result) {
if(result.equals(""))
{
info.setText(nfo);
matchArchive(matches);
//title
CharSequence ttl = "Team " + teamNum;
titlets.setText(ttl.toString());
loading.dismiss();
}
else
{
alert.setMessage(result);
alert.show();
}
}
}
Anything in there that could be causing this? :|
It may be that your thread priority may not be set very high. I remember the default is rather low. However, for what you're doing, it shouldn't be taking more than a couple seconds. I would think that the real problem lies in APIconnection going to the network and doing something that takes a long time. Particularly, that for loop that does the event fetching would be doing a lot of work if each call opens a new socket, assuming that this is for FIRST matches. :P
I am having the same issue, doing nothing more than a file copy with simple DES decryption... the whole thing ran in a few seconds on the UI thread, but when moved into an ASYNCTASK it is now taking MINUTES to accomplish. Unbelievable.