I would like to add some keywords to my app, so the API can recognize more efficiently the spoken words.
For example Im having trouble recognizing the some Italian words that starts with E ,(E` per me) for example. Or in German (er geht).
Here is my code:
public void recognize (int sampleRate) {
if (mApi == null) {
Log.w(TAG, "API not ready. Ignoring the request.");
return;
}
// Configure the API
mRequestObserver = mApi.streamingRecognize(mResponseObserver);
mRequestObserver.onNext(StreamingRecognizeRequest.newBuilder()
.setStreamingConfig(StreamingRecognitionConfig.newBuilder()
.setConfig(RecognitionConfig.newBuilder()
.setLanguageCode(getDefaultLanguageCode())
.setEncoding(RecognitionConfig.AudioEncoding.LINEAR16)
.setSampleRateHertz(sampleRate)
.build())
.setInterimResults(true)
.setSingleUtterance(true)
.build())
.build());
}
Setting the language for different cases :
private String getDefaultLanguageCode() {
SharedPreferences getLangSharedPrefs = getSharedPreferences("langSelected",0);
String selectedLanguage = getLangSharedPrefs.getString("langSelected", null);
switch (selectedLanguage) {
case "German":
langaugeCode = "de-DE";
break;
case "Italian":
langaugeCode = "it-IT";
break;
case "Spanish" :
langaugeCode = "es-ES";
break;
case "French" :
langaugeCode = "fr-FR";
break;
}
return langaugeCode;
}
I found the solution :
public void startRecognizing(int sampleRate) {
if (mApi == null) {
Log.w(TAG, "API not ready. Ignoring the request.");
return;
}
// Configure the API
mRequestObserver = mApi.streamingRecognize(mResponseObserver);
SpeechContext.Builder speechBuilder = SpeechContext.newBuilder();
speechBuilder.addPhrases("E per me");
speechBuilder.addPhrases("E");
mRequestObserver.onNext(StreamingRecognizeRequest.newBuilder()
.setStreamingConfig(StreamingRecognitionConfig.newBuilder()
.setConfig(RecognitionConfig.newBuilder()
.setLanguageCode(getDefaultLanguageCode())
.setEncoding(RecognitionConfig.AudioEncoding.LINEAR16)
.setSampleRateHertz(sampleRate)
.addSpeechContexts(speechBuilder)
.build())
.setInterimResults(true)
.setSingleUtterance(true)
.build())
.build());
}
Related
I am developing an Android security app and have decided to implement the PlayIntegrity API as an alternative to SafetyNet API. I have already completed the necessary setup steps such as enabling the Play and Cloud console, however, I am encountering an issue where I am getting an error 'GOOGLE SERVER UNAVAILABLE' when trying to obtain a token. Can anyone provide any insight into why this might be happening and possible solutions? Any help would be greatly appreciated.
Please see below code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// playIntegritySetup.lol();
getToken();
}
private void getToken() {
String nonce = Base64.encodeToString(generateNonce(50).getBytes(), Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
// Create an instance of a manager.
IntegrityManager integrityManager = IntegrityManagerFactory.create(getApplicationContext());
// Request the integrity token by providing a nonce.
Task<IntegrityTokenResponse> integrityTokenResponse = integrityManager.requestIntegrityToken(
IntegrityTokenRequest.builder()
.setNonce(nonce)
.build());
integrityTokenResponse.addOnSuccessListener(new OnSuccessListener<IntegrityTokenResponse>() {
#Override
public void onSuccess(IntegrityTokenResponse integrityTokenResponse) {
String integrityToken = integrityTokenResponse.token();
SplashActivity.this.doIntegrityCheck(integrityToken);
Log.e("Integrity Token", "integrity token from the app" + integrityToken);
}
});
integrityTokenResponse.addOnFailureListener(e -> showErrorDialog("Error getting token from Google. Google said: " + getErrorText(e)));
}
private void doIntegrityCheck(String token) {
AtomicBoolean hasError = new AtomicBoolean(false);
Observable.fromCallable(() -> {
OkHttpClient okHttpClient = new OkHttpClient();
Response response = okHttpClient.newCall(new Request.Builder().url("money control url" + "token from backend server" + token).build()).execute();
Log.e("Token", "token from the app" + token);
if (!response.isSuccessful()) {
hasError.set(true);
return "Api request error. Code: " + response.code();
}
ResponseBody responseBody = response.body();
if (responseBody == null) {
hasError.set(true);
return "Api request error. Empty response";
}
JSONObject responseJson = new JSONObject(responseBody.string());
if (responseJson.has("error")) {
hasError.set(true);
return "Api request error: " + responseJson.getString("error");
}
if (!responseJson.has("deviceIntegrity")) {
hasError.set(true);
}
return responseJson.getJSONObject("deviceIntegrity").toString();
}) // Execute in IO thread, i.e. background thread.
.subscribeOn(Schedulers.io())
// report or post the result to main thread.
.observeOn(AndroidSchedulers.mainThread())
// execute this RxJava
.subscribe(new Observer<String>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(String result) {
if (hasError.get()) {
if (result.contains("MEETS_DEVICE_INTEGRITY") && result.contains("MEETS_BASIC_INTEGRITY")) {
//Here goes my other code
}
}
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
});
}
private String getErrorText(Exception e) {
String msg = e.getMessage();
if (msg == null) {
return "Unknown Error";
}
//the error code
int errorCode = Integer.parseInt(msg.replaceAll("\n", "").replaceAll(":(.*)", ""));
switch (errorCode) {
case IntegrityErrorCode.API_NOT_AVAILABLE:
return "API_NOT_AVAILABLE";
case IntegrityErrorCode.NO_ERROR:
return "NO_ERROR";
case IntegrityErrorCode.INTERNAL_ERROR:
return "INTERNAL_ERROR";
case IntegrityErrorCode.NETWORK_ERROR:
return "NETWORK_ERROR";
case IntegrityErrorCode.PLAY_STORE_NOT_FOUND:
return "PLAY_STORE_NOT_FOUND";
case IntegrityErrorCode.PLAY_STORE_ACCOUNT_NOT_FOUND:
return "PLAY_STORE_ACCOUNT_NOT_FOUND";
case IntegrityErrorCode.APP_NOT_INSTALLED:
return "APP_NOT_INSTALLED";
case IntegrityErrorCode.PLAY_SERVICES_NOT_FOUND:
return "PLAY_SERVICES_NOT_FOUND";
case IntegrityErrorCode.APP_UID_MISMATCH:
return "APP_UID_MISMATCH";
case IntegrityErrorCode.TOO_MANY_REQUESTS:
return "TOO_MANY_REQUESTS";
case IntegrityErrorCode.CANNOT_BIND_TO_SERVICE:
return "CANNOT_BIND_TO_SERVICE";
case IntegrityErrorCode.NONCE_TOO_SHORT:
return "NONCE_TOO_SHORT";
case IntegrityErrorCode.NONCE_TOO_LONG:
return "NONCE_TOO_LONG";
case IntegrityErrorCode.GOOGLE_SERVER_UNAVAILABLE:
return "GOOGLE_SERVER_UNAVAILABLE";
case IntegrityErrorCode.NONCE_IS_NOT_BASE64:
return "NONCE_IS_NOT_BASE64";
default:
return "Unknown Error";
}
}
private String generateNonce(int length) {
String nonce = "";
String allowed = getNonce();
for (int i = 0; i < length; i++) {
nonce = nonce.concat(String.valueOf(allowed.charAt((int) Math.floor(Math.random() * allowed.length()))));
}
return nonce;
}
public native String getNonce();
static {
System.loadLibrary("all-keys");
}
I ran into the same problem and I found a solution for this.
You need to specify cloudProjectNumber() when you are working on outside of Google Play, which can be found in google cloud console.
Quote from the doc:
Important: In order to receive and decrypt Integrity API responses,
apps not available on Google Play need to include their Cloud project
number in their requests. You can find this in Project info in the
Google Cloud Console.
So the code should be like this:
IntegrityTokenRequest.builder()
.setNonce(nonce)
.cloudProjectNumber(100004676) // your cloud project number here for dev build
.build());
So, basically, I get an error when I try to upgrade a subscription using google pay billingclient api. When the user subscribes, it works fine but then if they want to upgrade their subscription it throws an error. The error is "user is not eligible for this purchase" I have tried to contact google support to get suggestions regarding this problem but I have not heard back from them yet.
It might be a problem from within my code so I am going to paste the code and I am open to suggestions as I have been working on resolving this error for a while now.
BillingClient version is 4.0.0
And I testing it in a closed test
The code is :
private void subscribe(SkuDetails skuDetails,String accountId,String profileId,int is_up,String token ){
int code =billingClient.isFeatureSupported(BillingClient.FeatureType.SUBSCRIPTIONS).getResponseCode();
BillingFlowParams billingFlowParams;
if(is_up ==0){
billingFlowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetails)
.setObfuscatedAccountId(accountId)
.setObfuscatedProfileId(profileId)
.build();
}else if(is_up==1){
billingFlowParams = BillingFlowParams.newBuilder()
.setObfuscatedAccountId(accountId)
.setObfuscatedProfileId(profileId)
.setSubscriptionUpdateParams(BillingFlowParams.SubscriptionUpdateParams.newBuilder()
.setOldSkuPurchaseToken(token.trim())
.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.DEFERRED)
.build())
.setSkuDetails(skuDetails)
.setVrPurchaseFlow(false)
.build();
}else {
billingFlowParams = BillingFlowParams.newBuilder()
.setObfuscatedAccountId(accountId)
.setObfuscatedProfileId(profileId)
.setSubscriptionUpdateParams(BillingFlowParams.SubscriptionUpdateParams.newBuilder()
.setOldSkuPurchaseToken(token.trim())
.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.DEFERRED)
.build())
.setSkuDetails(skuDetails)
.setVrPurchaseFlow(true)
.build();
}
int responseCode = billingClient.launchBillingFlow(getActivity(), billingFlowParams).getResponseCode();
}
#Override
public void do_payment(String token_id, String order_id,String prd_id,String account_id,String profile_id,int is_up,String token,String callback) {
callBacktoWeb =callback;
if(bBillingClientReady){
displaySubs(order_id,prd_id,account_id,profile_id,is_up,token);
}else {
Toast.makeText(mContext,"bBillingClient not Ready",Toast.LENGTH_SHORT).show();
}
}
}
private void displaySubs(String order_id,String prd_id,String accountId,String profileId,int is_up,String token){
mOrderId =order_id;
List<String> skuList = new ArrayList<>();
skuList.add(prd_id);
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.SUBS);
billingClient.querySkuDetailsAsync(params.build(),
new SkuDetailsResponseListener() {
#Override
public void onSkuDetailsResponse(BillingResult billingResult,
List<SkuDetails> skuDetailsList) {
if(billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK){
if(skuDetailsList!=null){
for (SkuDetails skuDetail:skuDetailsList){
subscribe(skuDetail,accountId,profileId,is_up,token);
}
}else {
Logger.d(PTAG,"skuDetailsList size:"+skuDetailsList.size());
}
}else {
}
}
});
}
I try to use Google Consent with the User Messaging Platform to show in Android app consent form. I follow this documentation https://developers.google.com/admob/ump/android/quick-start.
I get this error:
onConsentInfoUpdateFailure: Publisher misconfiguration: Failed to read publisher's account configuration; please check your configured app ID. Received app ID: `ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX`.
My Code:
ConsentRequestParameters params;
if (testingGDPR) {
ConsentDebugSettings debugSettings = new ConsentDebugSettings.Builder(this)
.setDebugGeography(ConsentDebugSettings.DebugGeography.DEBUG_GEOGRAPHY_EEA)
.addTestDeviceHashedId(getString(R.string.ADMOB_REAL_DEVICE_HASH_ID_FOR_TESTING))
.build();
params = new ConsentRequestParameters.Builder().setConsentDebugSettings(debugSettings).build();
} else {
params = new ConsentRequestParameters.Builder().build();
}
consentInformation = UserMessagingPlatform.getConsentInformation(this);
if (testingGDPR) {
consentInformation.reset();
}
consentInformation.requestConsentInfoUpdate(
this,
params,
new ConsentInformation.OnConsentInfoUpdateSuccessListener() {
#Override
public void onConsentInfoUpdateSuccess() {
if (consentInformation.isConsentFormAvailable() && consentInformation.getConsentStatus() == ConsentInformation.ConsentStatus.REQUIRED) {
loadForm();
} else {
setupAds();
}
}
},
new ConsentInformation.OnConsentInfoUpdateFailureListener() {
#Override
public void onConsentInfoUpdateFailure(FormError formError) {
Log.d("gdpr", "onConsentInfoUpdateFailure, code:" + formError.getErrorCode() + ", " + formError.getMessage());
}
});
The TestDeviceHashedId is not the same thing as the Admob Device Id.
So remove this line:
.addTestDeviceHashedId(getString(R.string.ADMOB_REAL_DEVICE_HASH_ID_FOR_TESTING))
Then run your code and check for the log. The TestDeviceHashedId you should use will appear.
I'm working on cache implementation with RxJava 2. What I need is when network request fails, my repository would insert stale data and show error message. While I'm able to insert Item with .onErrorReturnItem(cachedItem) the error gets lost. Also I'm able to concat cached data with network request, but it is a bit cumbersome:
public Observable<Dashboard> getDashboard(String phoneNum, boolean getNewData) {
if (getNewData) invalidateDashboardCache();//just set dashboardCacheValid = false
Observable<Dashboard> observableToCache = Observable.fromCallable(
() -> {
Dashboard cached = mCache.getDashboard(phoneNum);
if (cached != null) {
if (!cached.cacheValid()) {
dashboardCacheValid = false;
}
return cached;
}
dashboardCacheValid = false;
return Dashboard.EMPTY;
})
.concatMap(cachedDashboard -> Observable.concat(Observable.just(cachedDashboard),
Observable.fromCallable(() -> !dashboardCacheValid)
.filter(Boolean::booleanValue)
.flatMap(cacheNotValid -> mNetworkHelper.getDashboardRaw(phoneNum))
.doOnNext(dashboard -> {
mCache.putDashboard(pnumber, dashboard);
dashboardCacheValid = true;
})));
return cacheObservable(CACHE_PREFIX_GET_DASHBOARD + phoneNum, observableToCache); //this is for multiple calls
}
Is there a way to modify .onErrorReturnItem(cachedDashboard) to something like this?:
Thanks to #akarnokd I was able to solve it properly and with much cleaner code:
public Observable<Dashboard> getDashboardNew(String phoneNum, boolean getNewData) {
Dashboard fromCache = mCache.getDashboard(phoneNum, getNewData);
dashboardCacheValid = fromCache.cacheValid();
if (getNewData) invalidateDashboardCache();
if (dashboardCacheValid) {
return Observable.just(fromCache);
} else {
final Dashboard cached = fromCache;
Observable<Dashboard> observableToCache = mNetworkHelper.getDashboardRaw(phoneNum)
.doOnNext(dashboard -> mCache.putDashboard(phoneNum, dashboard))
.onErrorResumeNext(throwable -> {
return Observable.concat(Observable.just(cached), Observable.error(throwable));
});
return cacheObservable(CACHE_PREFIX_GET_DASHBOARD + phoneNum, observableToCache);
}
}
I have created a .NET backend Mobile Service on Windows Azure using the code sample provided on the website article.
Now I am trying to register a user with android client but I can't.
My backend registration control looks like below;
[AuthorizeLevel(AuthorizationLevel.Anonymous)]
public class CustomRegistrationController : ApiController
{
public ApiServices Services { get; set; }
// POST api/CustomRegistration
public HttpResponseMessage Post(RegistrationRequest registrationRequest)
{
if (!Regex.IsMatch(registrationRequest.username, "^[a-zA-Z0-9]{4,}$"))
{
return this.Request.CreateResponse(HttpStatusCode.BadRequest, "Invalid username (at least 4 chars, alphanumeric only)");
}
else if (registrationRequest.password.Length < 8)
{
return this.Request.CreateResponse(HttpStatusCode.BadRequest, "Invalid password (at least 8 chars required)");
}
hadContext context = new hadContext();
Account account = context.Accounts.Where(a => a.Username == registrationRequest.username).SingleOrDefault();
if (account != null)
{
return this.Request.CreateResponse(HttpStatusCode.BadRequest, "Username already exists");
}
else
{
byte[] salt = CustomLoginProviderUtils.generateSalt();
Account newAccount = new Account
{
Id = Guid.NewGuid().ToString(),
Username = registrationRequest.username,
Salt = salt,
SaltedAndHashedPassword = CustomLoginProviderUtils.hash(registrationRequest.password, salt)
};
context.Accounts.Add(newAccount);
context.SaveChanges();
return this.Request.CreateResponse(HttpStatusCode.Created);
}
}
}
I wrote this code on android client app
public void register(View view) {
if ( txtUsername.getText().toString().equals("")
&& txtPassword.getText().toString().equals(""))
{
Log.w(TAG,"tüm alanları girmen gerek");
return;
}
else
{
RegistrationRequest register = new RegistrationRequest();
register.setUsername(txtUsername.getText().toString());
register.setPassword(txtUsername.getText().toString());
mClient.invokeApi("CustomRegistration",register,RegistrationRequest.class,
new ApiOperationCallback<RegistrationRequest>() {
#Override
public void onCompleted(RegistrationRequest result, Exception exception, ServiceFilterResponse response) {
if (exception==null)
{
Log.w(TAG,"kayıt başarılı");
}
else
{
Log.w(TAG,"kayıt başarısız " +exception);
}
}
});
}
}
It's not working. How should I do for registration.