Can't start pocketsphinx in Unity3d game - android

I am trying to integrate PocketSphinx into my Unity3d project.
In order to do this, I have integrated the Android demo project into the Android Studio export of the Unity3d project.
When trying to the app, I get an exception saying that the following function retured -1.
public static final native void Decoder_setSearch(long var0, Decoder var2, String var3);
This method is being called when I start listening for voice commands:
recognizer.startListening("hello app", 10000);
Why does this happen? How can I resolve it?
It works perfectly in the PocketSphinx example project.
How I've set up the Recognizer:
Assets assets = new Assets(MyActivity.this);
File assetDir = assets.syncAssets();
recognizer = defaultSetup()
.setAcousticModel(new File(assetDir, "en-us-ptm"))
.setDictionary(new File(assetDir, "cmudict-en-us.dict"))
.setRawLogDir(assetDir)
.setKeywordThreshold(1e-45f)
.setBoolean("-allphone_ci", true)
.getRecognizer();
recognizer.addListener(MyActivity.this);
recognizer.addKeyphraseSearch(KWS_SEARCH, KEYPHRASE);
...and more info from logcat (complete file):
01-29 18:01:12.989 4237-4237/com.myName.pocketSphinxTest I/SpeechRecognizer: Start recognition "hello app"
01-29 18:01:12.989 4237-4237/com.myName.pocketSphinxTest D/AndroidRuntime: Shutting down VM
01-29 18:01:12.989 4237-4237/com.myName.pocketSphinxTest W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x4157fd58)
01-29 18:01:12.989 4237-4237/com.myName.pocketSphinxTest E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myName.pocketSphinxTest, PID: 4237
java.lang.Error: FATAL EXCEPTION [main]
Unity version : 5.2.2f1
Device model : Osterhout_Design_Group R7-W
Device fingerprint: R7/apq8084/apq8084:4.4.4/KTU84P/ODG_R7_V3.1.12:user/release-keys
01-29 18:01:13.019 4237-4237/com.myName.pocketSphinxTest I/Process: Sending signal. PID: 4237 SIG: 9

setSearch is called in startListening with the name of the search. The name of the search is "hello app" in your case. If the search "hello app" is not added before it returns -1 and throws exception. The source is available in pocketsphinx-android sources.
The error generally means you didn't add the search with the name "hello app" before, from your code you say that KWS_SEARCH has the same value of "hello app", but I think there is a typo. You need to double-check that you use the same string for the search name. I would recommend you to replace "hello app" string with KWS_SEARCH in startListening call.

Related

TFlite object detector app crashes just before making predictions

I tried several methods to deploy the tflite model on android, flutter, kotlin, etc, but andriod app keeps crashing when I want to make predictions. This was an error I got trying out the object detection codelab:
2022-01-01 15:52:55.965 2971-3034/org.tensorflow.codelabs.objectdetection E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1
Process: org.tensorflow.codelabs.objectdetection, PID: 2971
java.io.FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed
at android.content.res.AssetManager.nativeOpenAssetFd(Native Method)
at android.content.res.AssetManager.openFd(AssetManager.java:938)
at org.tensorflow.lite.task.core.TaskJniUtils.createHandleFromFdAndOptions(TaskJniUtils.java:65)
at org.tensorflow.lite.task.vision.detector.ObjectDetector.createFromFileAndOptions(ObjectDetector.java:147)
at org.tensorflow.codelabs.objectdetection.MainActivity.runObjectDetection(MainActivity.kt:127)
at org.tensorflow.codelabs.objectdetection.MainActivity.access$runObjectDetection(MainActivity.kt:48)
at org.tensorflow.codelabs.objectdetection.MainActivity$setViewAndDetect$1.invokeSuspend(MainActivity.kt:150)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
2022-01-01 15:52:56.014 2971-3034/org.tensorflow.codelabs.objectdetection I/Process: Sending signal. PID: 2971 SIG: 9
This issue was caused by android compressing the tflite model during the build. To solve this issue i had to instruct aapt not to compress the file.
go to build.gradle, at the app level, inside the andriod{} block, add
aaptOptions {
noCompress "model.tflite"
}
please rename model.tflite to your custom name if your tflite model is not named "model.tflite"

AdaptiveCard native method on android not found

i'm tring to launch the basic adaptive card example using maven central depencdency but i'm having an error because native method impl is not being found.
I have just add the dependency to my build.gradle:
compile 'io.adaptivecards:adaptivecards-android-arm:1.0.0'
This is the error:
11-13 18:19:55.944 16684-16970 E/zygote: No implementation found for long com.microsoft.adaptivecards.objectmodel.AdaptiveCardObjectModelJNI.AdaptiveCard_DeserializeFromString(java.lang.String) (tried Java_com_microsoft_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_AdaptiveCard_1DeserializeFromString and Java_com_microsoft_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_AdaptiveCard_1DeserializeFromString__Ljava_lang_String_2)
11-13 18:19:55.945 16684-16684 D/AndroidRuntime: Shutting down VM
11-13 18:19:55.949 16684-16684 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.tuenti.messenger, PID: 16684
java.lang.UnsatisfiedLinkError: No implementation found for long com.microsoft.adaptivecards.objectmodel.AdaptiveCardObjectModelJNI.AdaptiveCard_DeserializeFromString(java.lang.String) (tried Java_com_microsoft_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_AdaptiveCard_1DeserializeFromString and Java_com_microsoft_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_AdaptiveCard_1DeserializeFromString__Ljava_lang_String_2)
at com.microsoft.adaptivecards.objectmodel.AdaptiveCardObjectModelJNI.AdaptiveCard_DeserializeFromString(Native Method)
at com.microsoft.adaptivecards.objectmodel.AdaptiveCard.DeserializeFromString(AdaptiveCard.java:105)
I have checked the generated APK and it contains the SO for adaptive cards but still does not work.
Try adding a static ctor before accessing the API and see if that helps.
static {
System.loadLibrary("adaptivecards-native-lib");
}

Android.isUserAMonkey throws RuntimeException

I'm seeing exceptions when ActivityManager.isUserAMonkey() is run on older Android devices:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myapp.AndroidApp}: java.lang.RuntimeException: Unknown exception code: 1 msg null
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2781)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2797)
at android.app.ActivityThread.access$2300(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2132)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:4914)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Unknown exception code: 1 msg null
at android.os.Parcel.readException(Parcel.java:1257)
at android.os.Parcel.readException(Parcel.java:1235)
at android.app.ActivityManagerProxy.isUserAMonkey(ActivityManagerNative.java:2762)
at android.app.ActivityManager.isUserAMonkey(ActivityManager.java:990)
at <com.myapp....> ...
There is a bit of discussion of the bug here (including a classic thats-not-possible response from one of the developers: "In the standard platform implementation this is pretty much not possible.")
https://groups.google.com/forum/?fromgroups=#!topic/android-developers/tQJcM4O4WxM
Its not clear to me if this always happens, or only happens when running under a test monkey, or only on some devices or what. (I'm running into this problem using Apkudo's device testing service, where the user is always a monkey.) Its not clear when this was fixed, either (it doesn't happen on most (all?) newer devices).
The exception seems to be restricted to Android 2.2 (SDK version 8) releases. And seems to have been a bug in android.app.ActivityManagerNative.
Here's the 2.2.1 code (found in ActivityManagerNative.java on grepcode.com):
1248 case IS_USER_A_MONKEY_TRANSACTION: {
1249 data.enforceInterface(IActivityManager.descriptor);
1250 reply.writeInt(isUserAMonkey() ? 1 : 0);
1251 reply.writeNoException();
1252 return true;
1253 }
Here's the 2.3.1 code (which seems to be the same as much more recent 4.x code which I know works correctly). (Also found on grepcode.com):
1248 case IS_USER_A_MONKEY_TRANSACTION: {
1239 data.enforceInterface(IActivityManager.descriptor);
1240 boolean areThey = isUserAMonkey();
1241 reply.writeNoException();
1242 reply.writeInt(areThey ? 1 : 0);
1243 return true;
1244 }
Notice the order of writeNoException and writeInt are reversed in the newer code. The corresponding code to read the parcel seems to be unchanged since 2.2.1 as far as I can tell:
2749 public boolean isUserAMonkey() throws RemoteException {
2750 Parcel data = Parcel.obtain();
2751 Parcel reply = Parcel.obtain();
2752 data.writeInterfaceToken(IActivityManager.descriptor);
2753 mRemote.transact(IS_USER_A_MONKEY_TRANSACTION, data, reply, 0);
2754 reply.readException();
2755 boolean res = reply.readInt() != 0;
2756 data.recycle();
2757 reply.recycle();
2758 return res;
2759 }
This side reads the exception first, then expects the data.
The javadoc for Parcel readException and writeException imply that they record the exception in the parcel's header (and thus shouldn't impact the actual data in the parcel), but it seems the order does matter.
This means on SDK version 8 the ActivietyManager.isUserAMonkey() API will always throw an exception, monkey or not. Android builds after SDK 8 should not throw this exception.
I suspect the SDK 8 exception message might be slightly different without a monkey ("1 msg null" vs. maybe "0 msg null"?), but don't have an example of the exception without a monkey running.

Method not found using DigestUtils in Android

I am trying to use the library DigestUtils in Android 2.3.1 using JDK 1.6, however I get the following error when executing the app:
Could not find method org.apache.commons.codec.binary.Hex.encodeHexString, referenced from method org.apache.commons.codec.digest.DigestUtils.shaHex
Here you have the stacktrace:
02-03 10:25:45.153: I/dalvikvm(1230): Could not find method org.apache.commons.codec.binary.Hex.encodeHexString, referenced from method org.apache.commons.codec.digest.DigestUtils.shaHex
02-03 10:25:45.153: W/dalvikvm(1230): VFY: unable to resolve static method 329: Lorg/apache/commons/codec/binary/Hex;.encodeHexString ([B)Ljava/lang/String;
02-03 10:25:45.153: D/dalvikvm(1230): VFY: replacing opcode 0x71 at 0x0004
02-03 10:25:45.153: D/dalvikvm(1230): VFY: dead code 0x0007-0008 in Lorg/apache/commons/codec/digest/DigestUtils;.shaHex ([B)Ljava/lang/String;
02-03 10:25:45.163: D/AndroidRuntime(1230): Shutting down VM
02-03 10:25:45.163: W/dalvikvm(1230): threadid=1: thread exiting with uncaught exception (group=0x40015560)
02-03 10:25:45.173: E/AndroidRuntime(1230): FATAL EXCEPTION: main
02-03 10:25:45.173: E/AndroidRuntime(1230): java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Hex.encodeHexString
02-03 10:25:45.173: E/AndroidRuntime(1230): at org.apache.commons.codec.digest.DigestUtils.md5Hex(DigestUtils.java:226)
02-03 10:25:45.173: E/AndroidRuntime(1230): at com.caumons.trainingdininghall.ConnectionProfileActivity.onCreate(ConnectionProfileActivity.java:20)
02-03 10:25:45.173: E/AndroidRuntime(1230): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
02-03 10:25:45.173: E/AndroidRuntime(1230): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1586)
02-03 10:25:45.173: E/AndroidRuntime(1230): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1638)
02-03 10:25:45.173: E/AndroidRuntime(1230): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
02-03 10:25:45.173: E/AndroidRuntime(1230): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:928)
02-03 10:25:45.173: E/AndroidRuntime(1230): at android.os.Handler.dispatchMessage(Handler.java:99)
02-03 10:25:45.173: E/AndroidRuntime(1230): at android.os.Looper.loop(Looper.java:123)
02-03 10:25:45.173: E/AndroidRuntime(1230): at android.app.ActivityThread.main(ActivityThread.java:3647)
02-03 10:25:45.173: E/AndroidRuntime(1230): at java.lang.reflect.Method.invokeNative(Native Method)
02-03 10:25:45.173: E/AndroidRuntime(1230): at java.lang.reflect.Method.invoke(Method.java:507)
02-03 10:25:45.173: E/AndroidRuntime(1230): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
02-03 10:25:45.173: E/AndroidRuntime(1230): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
02-03 10:25:45.173: E/AndroidRuntime(1230): at dalvik.system.NativeStart.main(Native Method)
The line of code which causes the exception is:
String hash = DigestUtils.shaHex("textToHash");
I have executed the same code in a Java class outside Android and it works! So, I do not know why when working with Android it does not work... I put the libraty inside a new libs/ folder in my app and updated the BuildPath to use it. If I try to use md5 instead of sha1 I get the same exception. Any help would be appreciated! Thank you.
UPDATE:
As this is a very active question, I've changed the accepted answer in favour of #DA25, as his solution is straightforward and the high number of upvotes prove that it works.
I ran into the same issue trying to use DigestUtils in my Android app. This was the best answer I could find by searching, but I was reluctant to rebuild the .jar file with the namespace changed. After spending some time on this issue, I found an easier way to solve the problem for my case. The problem statement for my code was
String s = DigestUtils.md5Hex(data);
Replace this statement with the following and it will work:
String s = new String(Hex.encodeHex(DigestUtils.md5(data)));
Similarly, for shaHex exampl, you can change it to
String hash = new String(Hex.encodeHex(DigestUtils.sha("textToHash")));
This works because even though Android does not have encodeHexString(), it does have encodeHex(). Hope this would help others who run into the same issue.
Since there's no clear answer for the root cause of this problem, I'd like to clarify what's happening here.
Why the NoSuchMethodError is thrown in the first place?
According to exception stack trace, the line that causes the fault is 226 in DigestUtils#md5hex method. Let's see what we have there (I'm assuming you have used version 1.4, since this is the only release where Hex#encodeHexString method is being invoked in line 226):
public static String md5Hex(String data) {
return Hex.encodeHexString(md5(data));
}
The exception says java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Hex.encodeHexString.
Let's understand why.
First of all, Android framework already includes the Commons Codec library (except the DigestUtils class). Yes, it is not exposed as part of the Android SDK and you cannot use it directly. But you still want to use it. So what you do? You add Commons Codec library as part of your application. The compiler doesn't complain - from his point of view everything was fine.
But what happens at runtime? Let's follow your exception stack trace:
First, you're calling DigestUtils#md5Hex from your Activity's onCreate method. As I wrote above, the framework doesn't include that class, so DigestUtils (from Commons Codec version 1.4) is loaded from your dex.
Next, md5hex method tries to invoke Hex#encodeHexString method. Hex class is part of the Commons Codec library that included in framework. The thing is that its version is 1.3 (ancient release from July 2004). Hex class exists in boot classpath, which means that the runtime will always favor it instead of the Hex class that packaged inside your dex. You can see warnings about it in your application logs when you start your app (with Dalvik runtime):
D/dalvikvm? DexOpt: 'Lorg/apache/commons/codec/binary/Hex;' has an earlier definition; blocking out
I/dalvikvm? DexOpt: not resolving ambiguous class 'Lorg/apache/commons/codec/binary/Hex;'
D/dalvikvm? DexOpt: not verifying/optimizing 'Lorg/apache/commons/codec/binary/Hex;': multiple definitions
I/dalvikvm? Could not find method org.apache.commons.codec.binary.Hex.encodeHexString, referenced from method org.apache.commons.codec.digest.DigestUtils.md5Hex
Hex#encodeHexString method was introduced in version 1.4 of Commons Codec library and therefore it doesn't exist in framework's Hex class. The runtime can't find this method and thus throws NoSuchMethodError exception.
Why the accepted answer's solution works?
String s = new String(Hex.encodeHex(DigestUtils.md5(data)));
First, DigestUtils#md5 method is called. As I already stated, DigestUtils class that will be used is the one that packaged in your dex. This method doesn't use any other Commons Codec classes, so no problem with it.
Next, Hex#encodeHex will be called. The Hex class that will be used is the framework's one (version 1.3). The encodeHex method (that takes a single parameter - byte array) exists in version 1.3 of Commons Codec library, and therefore this code will work fine.
What would I suggest?
My suggested solution is to rename the classes namespace/package. By doing so I'm explicitly specifying which code is going to execute, and prevent bizarre behavior that may occur because of versioning issues.
You can do it manually (as Caumons wrote in his answer), or automatically with jarjar tool.
See this issue summary and tips for using jarjar in my blogpost.
Finally I get the answer and it works well. As described in No such method error in Apache codec for another type of encrypt (Base64) I tried to reproduce the same issue and I get exactly the same error. So I was in the case of the question attached. As they say, it seems to be an internal name collision with the package name org.apache.commons.codec and as stated by #Don I changed it to com.apache.commons.codec and worked fine! How I did it?
I downloaded the source code and changed the 3 directories org to com. I also replaced all the occurrences of the package name in the files where they appear and also changed the references in the docs to com/apache/commons/codec/. (Do not try to remane them manually or you will spend the hole day). Then I compiled the library and generated the jar with Ant, which I called commons-codec-1.6-android.jar. I put the jar in the libs/ folder of my Android app and added it to the buildpath. Also, I attached the sources as the folder which contains all the files. So now I have the library ready to use with Android!
Hope that it helps someone else!
Thanks #DA25
This is working fine for me
I have add dependency
compile 'commons-codec:commons-codec:1.9'
ref: http://mvnrepository.com/artifact/commons-codec/commons-codec/1.9
my function
public String encode(String key, String data) {
try {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
sha256_HMAC.init(secret_key);
return new String(Hex.encodeHex(sha256_HMAC.doFinal(data.getBytes("UTF-8"))));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
For me proguard removed the class during obfuscation .Add this to your Proguard rules.
-keep class org.apache.commons.** { *; }
Here's the method I was using of apache package.
Hex.encodeHex(digest)
Add method
public static String byteArrayToHexString(byte[] bytes) {
final char[] toDigits = "0123456789abcdef".toCharArray();
int l = bytes.length;
char[] out = new char[l << 1];
int i = 0; for (int j = 0; i < l; ++i) {
out[(j++)] = toDigits[((0xF0 & bytes[i]) >>> 4)];
out[(j++)] = toDigits[(0xF & bytes[i])];
}
return new String(out);
}
We used below code and it worked :
HmacUtils hmacUtils = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, keyString);
String digest = new String( Hex.encodeHex(hmacUtils.hmac(msg)));
Another way to rename DigestUtils class will be with proguard.
If you are not using proguard you can enable it and add this one line which will obfuscate only DigestUtils class, and leave everything else intact.
-keep class !org.apache.commons.codec.digest.DigestUtils,com.** { *; }
and add this to your app build.gradle
buildTypes {
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
Or OPTION 2
Use old version of the library in your code:
implementation("commons-codec:commons-codec:1.3"){
force = true
}
Need to use force = true if common-codec dependency come from third part library otherwise Gradle will resolve by default to higher version.

NullPointerException after finishing SFTP transfer

I'm receiving a null pointer execption at the end of a SFTP session.
What am I missing ?
This the error :
09-05 16:38:05.844 9298-9307/? E/System: Uncaught exception thrown by finalizer
09-05 16:38:05.844 9298-9307/? E/System: java.lang.NullPointerException
at com.enterprisedt.net.j2ssh.sftp.SftpFileOutputStream.finalize(SftpFileOutputStream.java:203)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:187)
at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:170)
at java.lang.Thread.run(Thread.java:841)
NO errors from the library during the SFTP session.
Basically I log in to the SFTP server calling these functions :
boolean success = sftp.Connect(hostname,22);
..........
CkSshKey key = new CkSshKey();
..........
String privKey = key.loadText(keypath);
..........
key.put_Password(password);
...........
success = key.FromOpenSshPrivateKey(privKey);
...........
success = sftp.AuthenticatePk(mPrefs.getSftpSapUser(),key);
Then I send the file :
Boolean success = sftp.InitializeSftp();
.............
success = sftp.UploadFileByName(remoteFilePath,localFilePath);
.............
sftp.SetPermissions(remoteFilePath, false, 511);
What am I missing ?
Thanks
This is not a crash in Chilkat. Look closely at the exception information:
com.enterprisedt.net.j2ssh.sftp.SftpFileOutputStream
The crash is in another software vendor's class (EnterpriseDT). Or more accurately: It might be a crash caused by incorrect usage of that vendor's class. It's not necessarily a defect in that vendor's software. (I really don't know..)

Categories

Resources