I really struggle with this since a while :( as I need an solution that works within UNITY3D.
I need to check if the user has given the permission to access the Android device camera (and location on a second level).
Normally the app start by asking for this permissions at launch, but if the user denies the access for the camera I need to know and check that later.
Otherwise the user could hit the camera UI button I made and try to access the camera via webcamtexture... and that leads into a crash of the app.
Since Android API 23 you cannot ignore or already grant permissions by changing the android manifest like I tried after reading several posts about that.
Thank's to everyone who has an idea to solve this.
Check this library: https://github.com/sanukin39/UniAndroidPermission
In that library I got these methods to check and request Permission.
public static void requestPermission(String permissionStr){
if(!hasPermission(permissionStr)) {
UnityPlayer.currentActivity.requestPermissions(new String[]{permissionStr}, 0);
}
}
public static boolean hasPermission(String permissionStr) {
if(Build.VERSION.SDK_INT < 23) {
return true;
}
Context context = UnityPlayer.currentActivity.getApplicationContext();
return context.checkCallingOrSelfPermission(permissionStr) == PackageManager.PERMISSION_GRANTED;
}
Hope it helps:)
I've seen SO question Can you request permissions synchronously in Android Marshmallow (API 23)'s runtime permissions model?. The answer is no.
Hence, I added a code as below (simplified version):
public class MyActivity ... {
private boolean hasGotPermissionRequestResult = false;
#Override
public void onCreate(...) {
if (ContextCompat.checkSelfPermission(...) == PackageManager.PERMISSION_DENIED) {
ActivityCompat.requestPermission(...);
while (!hasGotPermissionRequestResult) {}
}
}
#Override
public void onRequestPermissionResult(...) {
// whether granted or not
hasGotPermissionRequestResult = true;
}
}
However, I am not sure whether my approach is nice, safe and efficient.
Well, what you trying to achieve simply ain't possible, however there are several ways to overcome this:
Only trigger the method you wanna call when the permission is granted.
If you'd like to make the User only uses your app because that particular permission is so important that your app will not function without it, then use an educated screen to tell the users why you would want to use this permission in an intro screen kinda way.
I've created a library just for this kind of scenario where the library simplify the Permissions for you, it can be also used as a stand Alone Activity that has an Intro to your permission. you could check it out in Github PermissionHelper Github
In my app, I ask for permission to access SMS in Android SDK 23 (runtime permission) but the problem is dialog screen overlay showed up and access not granted .i disabled all another apps overlay but nothing changed.
I found this link but not helped
and the question is how can I fix it programmatically?
Ok,
finally I found the solution, I search all the web and can't find anything useful.
The answer is: When you ask for new permission don't ever do something else like showing toast or.... In my case I restart my app and ask for the next permission I use this code for restart the app.
Good luck.
Here is your solution: https://gist.github.com/Aeonitis/2337b1ca652173839395be82db7d05c3
If you have any questions, let me know.
Or you can delay your code execution by using postDelayed
(new Handler()).postDelayed(new Runnable() {
#Override
public void run() {
// do something
}
}, 500); // it doesn't hurt to wait 500ms is it?
It looks as though Google has made offline speech recognition available from Google Now for third-party apps. It is being used by the app named Utter.
Has anyone seen any implementations of how to do simple voice commands with this offline speech rec? Do you just use the regular SpeechRecognizer API and it works automatically?
Google did quietly enable offline recognition in that Search update, but there is (as yet) no API or additional parameters available within the SpeechRecognizer class. {See Edit at the bottom of this post} The functionality is available with no additional coding, however the user’s device will need to be configured correctly for it to begin working and this is where the problem lies and I would imagine why a lot of developers assume they are ‘missing something’.
Also, Google have restricted certain Jelly Bean devices from using the offline recognition due to hardware constraints. Which devices this applies to is not documented, in fact, nothing is documented, so configuring the capabilities for the user has proved to be a matter of trial and error (for them). It works for some straight away – For those that it doesn't, this is the ‘guide’ I supply them with.
Make sure the default Android Voice Recogniser is set to Google not
Samsung/Vlingo
Uninstall any offline recognition files you already have installed
from the Google Voice Search Settings
Go to your Android Application Settings and see if you can uninstall
the updates for the Google Search and Google Voice Search
applications.
If you can't do the above, go to the Play Store see if you have the
option there.
Reboot (if you achieved 2, 3 or 4)
Update Google Search and Google Voice Search from the Play Store (if
you achieved 3 or 4 or if an update is available anyway).
Reboot (if you achieved 6)
Install English UK offline language files
Reboot
Use utter! with a connection
Switch to aeroplane mode and give it a try
Once it is working, the offline recognition of other languages,
such as English US should start working too.
EDIT: Temporarily changing the device locale to English UK also seems to kickstart this to work for some.
Some users reported they still had to reboot a number of times before it would begin working, but they all get there eventually, often inexplicably to what was the trigger, the key to which are inside the Google Search APK, so not in the public domain or part of AOSP.
From what I can establish, Google tests the availability of a connection prior to deciding whether to use offline or online recognition. If a connection is available initially but is lost prior to the response, Google will supply a connection error, it won’t fall-back to offline. As a side note, if a request for the network synthesised voice has been made, there is no error supplied it if fails – You get silence.
The Google Search update enabled no additional features in Google Now and in fact if you try to use it with no internet connection, it will error. I mention this as I wondered if the ability would be withdrawn as quietly as it appeared and therefore shouldn't be relied upon in production.
If you intend to start using the SpeechRecognizer class, be warned, there is a pretty major bug associated with it, which require your own implementation to handle.
Not being able to specifically request offline = true, makes controlling this feature impossible without manipulating the data connection. Rubbish. You’ll get hundreds of user emails asking you why you haven’t enabled something so simple!
EDIT: Since API level 23 a new parameter has been added EXTRA_PREFER_OFFLINE which the Google recognition service does appear to adhere to.
Hope the above helps.
I would like to improve the guide that the answer https://stackoverflow.com/a/17674655/2987828 sends to its users, with images. It is the sentence "For those that it doesn't, this is the ‘guide’ I supply them with." that I want to improve.
The user should click on the four buttons highlighted in blue in these images:
Then the user can select any desired languages. When the download is done, he should disconnect from network, and then click on the "microphone" button of the keyboard.
It worked for me (android 4.1.2), then language recognition worked out of the box, without rebooting. I can now dictates instructions to the shell of Terminal Emulator ! And it is twice faster offline than online, on a padfone 2 from ASUS.
These images are licensed under cc by-sa 3.0 with attribution required to stackoverflow.com/a/21329845/2987828 ; you may hence add these images anywhere along with this attribution.
(This the standard policy of all images and texts at stackoverflow.com)
A simple and flexible offline recognition on Android is implemented by CMUSphinx, an open source speech recognition toolkit. It works purely offline, fast and configurable It can listen continuously for keyword, for example.
You can find latest code and tutorial here.
Update in 2019: Time goes fast, CMUSphinx is not that accurate anymore. I recommend to try Kaldi toolkit instead. The demo is here.
In short, I don't have the implementation, but the explanation.
Google did not make offline speech recognition available to third party apps. Offline recognition is only accessable via the keyboard. Ben Randall (the developer of utter!) explains his workaround in an article at Android Police:
I had implemented my own keyboard and was switching between Google
Voice Typing and the users default keyboard with an invisible edit
text field and transparent Activity to get the input. Dirty hack!
This was the only way to do it, as offline Voice Typing could only be
triggered by an IME or a system application (that was my root hack) .
The other type of recognition API … didn't trigger it and just failed
with a server error. … A lot of work wasted for me on the workaround!
But at least I was ready for the implementation...
From Utter! Claims To Be The First Non-IME App To Utilize Offline Voice Recognition In Jelly Bean
I successfully implemented my Speech-Service with offline capabilities by using onPartialResults when offline and onResults when online.
I was dealing with this and I noticed that you need to install the offline package for your Language. My language setting was "Español (Estados Unidos)" but there is not offline package for that language, so when I turned off all network connectivity I was getting an alert from RecognizerIntent saying that can't reach Google, then I change the language to "English (US)" (because I already have the offline package) and launched the RecognizerIntent it just worked out.
Keys: Language setting == Offline Voice Recognizer Package
It is apparently possible to manually install offline voice recognition by downloading the files directly and installing them in the right locations manually. I guess this is just a way to bypass Google hardware requirements.
However, personally I didn't have to reboot or anything, simply changing to UK and back again did it.
Working example is given below,
MyService.class
public class MyService extends Service implements SpeechDelegate, Speech.stopDueToDelay {
public static SpeechDelegate delegate;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//TODO do something useful
try {
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
((AudioManager) Objects.requireNonNull(
getSystemService(Context.AUDIO_SERVICE))).setStreamMute(AudioManager.STREAM_SYSTEM, true);
}
} catch (Exception e) {
e.printStackTrace();
}
Speech.init(this);
delegate = this;
Speech.getInstance().setListener(this);
if (Speech.getInstance().isListening()) {
Speech.getInstance().stopListening();
} else {
System.setProperty("rx.unsafe-disable", "True");
RxPermissions.getInstance(this).request(permission.RECORD_AUDIO).subscribe(granted -> {
if (granted) { // Always true pre-M
try {
Speech.getInstance().stopTextToSpeech();
Speech.getInstance().startListening(null, this);
} catch (SpeechRecognitionNotAvailable exc) {
//showSpeechNotSupportedDialog();
} catch (GoogleVoiceTypingDisabledException exc) {
//showEnableGoogleVoiceTyping();
}
} else {
Toast.makeText(this, R.string.permission_required, Toast.LENGTH_LONG).show();
}
});
}
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
//TODO for communication return IBinder implementation
return null;
}
#Override
public void onStartOfSpeech() {
}
#Override
public void onSpeechRmsChanged(float value) {
}
#Override
public void onSpeechPartialResults(List<String> results) {
for (String partial : results) {
Log.d("Result", partial+"");
}
}
#Override
public void onSpeechResult(String result) {
Log.d("Result", result+"");
if (!TextUtils.isEmpty(result)) {
Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onSpecifiedCommandPronounced(String event) {
try {
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
((AudioManager) Objects.requireNonNull(
getSystemService(Context.AUDIO_SERVICE))).setStreamMute(AudioManager.STREAM_SYSTEM, true);
}
} catch (Exception e) {
e.printStackTrace();
}
if (Speech.getInstance().isListening()) {
Speech.getInstance().stopListening();
} else {
RxPermissions.getInstance(this).request(permission.RECORD_AUDIO).subscribe(granted -> {
if (granted) { // Always true pre-M
try {
Speech.getInstance().stopTextToSpeech();
Speech.getInstance().startListening(null, this);
} catch (SpeechRecognitionNotAvailable exc) {
//showSpeechNotSupportedDialog();
} catch (GoogleVoiceTypingDisabledException exc) {
//showEnableGoogleVoiceTyping();
}
} else {
Toast.makeText(this, R.string.permission_required, Toast.LENGTH_LONG).show();
}
});
}
}
#Override
public void onTaskRemoved(Intent rootIntent) {
//Restarting the service if it is removed.
PendingIntent service =
PendingIntent.getService(getApplicationContext(), new Random().nextInt(),
new Intent(getApplicationContext(), MyService.class), PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
assert alarmManager != null;
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
super.onTaskRemoved(rootIntent);
}
}
For more details,
https://github.com/sachinvarma/Speech-Recognizer
Hope this will help someone in future.
My problem is basically that Android Studio wont deploy my app with my changes in the new code. Heres my case scenario:
I have a wifi direct code working like this (just testing with its methods):
public void peerDiscovery(){
mWifiDirectManager.discoverPeers(mChannel,
new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
Log.v(TAG,"Discovery Peers Success");
}
#Override
public void onFailure(int reason) {
Log.e(TAG,"Error on Discovery Peers, code: "+reason);
}
});
}
The above code works and then I decided to change it by adding the method: setPeerDiscoveryHandler(boolean isSuccess);
After the changes my code was as follows:
public void peerDiscovery(){
mWifiDirectManager.discoverPeers(mChannel,
new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
setPeerDiscoveryHandler(true);
Log.v(TAG, "Message Sent");
}
#Override
public void onFailure(int reason) {
Log.e(TAG,"Error on Discovery Peers, code: "+reason);
setPeerDiscoveryHandler(false);
}
});
}
But guess what, even after doing this new code and clicking on the Run button, it was like I didnt do nothing! And I realized that was happening after I started to check my logcat and the message:
"Discovery Peers Success"
was being printed, but I had it removed from the code (as you can see in my new code). I tried to rebuild and clean the project, uninstall the application from the mobile before deploying it again, but nothing seems to take effect. Any thoughts about it ?
Thanks in advance for all help guyz.
Well guyz, turns out that I found the solution for that problem of mine. Actually, I dont know why, but when that starts to happen you need to click on a button called "Sync Project with Gradle Files", and it will sync all your project files all over again. Like I said before, I really dont understand why that is needed, but in case someone have this problem in the future thats a solution. Thanks.
Android studio 4.2.x
This solved my problem:
In Android Studio, go to Run > Edit Configurations -> Disable "Allow parallel run"
Just go to "File -> Settings -> Build, Execution, Deployement -> Deplyoyment ->" and just disable the automatic Perform Run when ApplyChanges fails.