Fail to bind InAppBillingService when using IabHelper - android

I'm currently developing a game and try to implement In-app billing V3 of Google Play. I had followed the In-app sample and used IabHelper. However, when running the app in device, something goes wrong. I found that after mHelper.startSetup, neither onServiceDisconnected nor onServiceConnected was called. So I printed the result of mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE); in the IabHelper Class. The result is false.
Here is my code:
private IabHelper mHelper;
// MainActivity onCreate
protected void onCreate(Bundle savedInstanceState){
// ...
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.enableDebugLogging(true);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
return;
}
if (mHelper == null) return;
}
});
}
And in the method startSetup of IabHelper Class:
public void startSetup(final OnIabSetupFinishedListener listener) {
// ...
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
if (!mContext.getPackageManager().queryIntentServices(serviceIntent, 0).isEmpty()) {
// service available to handle that Intent
boolean bRes = mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
// ### I printed the result here it was false
Log.i("IAB", "IAB Service Result = " + bRes);
}
else {
// no service available to handle that Intent
if (listener != null) {
listener.onIabSetupFinished(
new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE,
"Billing service unavailable on device."));
}
}
}
I don't know the problem. I have done:
add permission: com.android.vending.BILLING
copy the .aidl file from sample to /src/com/android/vending/billing
my android target set to android-22
Any ideas what's wrong?
Thanks in advance.

Finally, I solved it by uploading the latest version of my game to developer console and debug the latest apk. The problem is gone. Hope this helps someone.

Copy all the class from util folder from the Project "Trivial"
or you can copy whole Util package into your project. And then give a try.

I had this problem, and found that
The app version debugged must be the same as the version released in developer console.
Play service needs to be available, some phones may actually kill the service after a screen lock, start play store, then redo the binding worked.
Using IabHelper out of box may trigger problems like service disconnect not handled, re-initialize fail, I had to modify it a bit.

Related

BillingClient always returns SERVICE_DISCONNECTED

So I have a billing client which I instantiate with
billingClient = BillingClient.newBuilder(this).setListener(this).build();
I then call
billingClient.startConnection(new BillingClientStateListener() {
#Override
public void onBillingSetupFinished(int responseCode) {
//TODO: use this for stuff
com.android.billingclient.api.Purchase.PurchasesResult result;
result = billingClient.queryPurchases(BillingClient.SkuType.SUBS);
Timber.d(result.toString());
}
#Override
public void onBillingServiceDisconnected() {
//TODO: use this for stuff
Timber.d("something went wrong ");
}
});
for whatever reason the breakpoint on the timber line always returns disconnected. can anyone provide insight or an example to how i would do this?
I came across this problem.
Be also sure to start the connection:
mBillingClient = BillingClient.newBuilder(mContext).setListener(purchasesUpdatedListener).build();
mBillingClient.startConnection(new BillingClientStateListener() {
#Override
public void onBillingSetupFinished(#BillingClient.BillingResponse int billingResponseCode) {
if (billingResponseCode == BillingClient.BillingResponse.OK) {
Log.d(TAG, "onBillingSetupFinished: BillingClient.BillingResponse.OK ");
}
}
#Override
public void onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
});
Turns out I was not using a version of my apk that was signed with the right version numbering and such. Once I fixed that I was able to connect to play services and figure out what i wanted.
I know it's too late to answer this, but i was missing this permission in manifest,
<uses-permission android:name="com.android.vending.BILLING" />
hope that helps someone
If you use custom rom or rooted device it probably won't work.
Run a system image on which the Google Play client application is preinstalled.
If Google Play is not preinstalled in the system image, your application won't be able to communicate with the Google Play licensing server.
https://developer.android.com/google/play/licensing/setting-up

Force an activity to remain in memory

I have implemented in app billing in a game. We are using unity3d as our game development engine . For in app billing to work I wrote a java native plugin that handles in app billing jobs and send messages back to unity application when purchase is done.
The way I implemented this is to start another activity to handle billing tasks and finish that activity after the tasks are done to return to unity app. But the problem is that in some devices(specially with low RAM) the unity app get closed when the billing activity is started . So when the user purchase an item our listeners in unity app are no longer valid and the unity app is restarted. We can't give them the item which is bought (It's consumed).
So my question is that is there any way to force the unity app remain untouched while the billing activity is running ?
My Code that fires billing activity:
public static void Buy(String SKU,String developerPayLoad,boolean Consumable)
{
Intent buyIntent = new Intent(gameActivity,MyketActivity.class);
buyIntent.putExtra("OPERATION", "PURCHASE");
buyIntent.putExtra("SKU", SKU);
buyIntent.putExtra("PayLoad", developerPayLoad);
buyIntent.putExtra("Consumable", Consumable);
gameActivity.startActivityForResult(buyIntent, 8586);
}
//The billing activity's OnCreate
protected void onCreate(Bundle bundle)
{
String Operation = getIntent().getStringExtra("OPERATION");
super.onCreate(bundle);
if(!FirstTime)
{
MyketHelper.Log("Not for the First Time");
finish();
return;
}
if(Operation.equals("PURCHASE"))
{
if(MyketHelper.helper==null)
{
finish();
return;
}
MyketHelper.Log("Purchase Flow Launched");
SKU = getIntent().getStringExtra("SKU");
PayLoad = getIntent().getStringExtra("PayLoad");
Consumeable = getIntent().getBooleanExtra("Consumable", true);
MyketHelper.helper.launchPurchaseFlow(this, SKU, 8585, OnPurchase);
}
}

how to connect to google play service and load leaderboard

I want to connect my game with google play service. i have read documentation on android developer and try to following type-a-number sample and still can't load leaderboard.
i have import baseGameUtils, but i use andengine so i didn't use extends BaseGameActivity from google.
what i have until now:
- GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) return success
- startActivityForResult(pickAccountIntent, REQUEST_CODE_PICK_ACCOUNT); is working well and i got my account name from onActivityResult(..);
- i already put this on my manifest.
<meta-data android:name="com.google.android.gms.games.APP_ID"
android:value="#string/app_id" />
my questions are
1. can i use google play service without extends BaseGameActivity?
2. if i use gameHelper.beginUserInitiatedSignIn(); after i got my account name, i got this on log cat. (what this connected mean? because i still got error on next question)
08-25 00:09:01.890: D/BaseGameActivity(11222): isGooglePlayServicesAvailable returned 0
08-25 00:09:01.890: D/BaseGameActivity(11222): beginUserInitiatedSignIn: starting new sign-in flow.
08-25 00:09:01.890: D/BaseGameActivity(11222): All clients now connected. Sign-in successful.
08-25 00:09:01.890: D/BaseGameActivity(11222): All requested clients connected. Sign-in succeeded!
3 . how do i use connect()? i have read and tried about gameClient and GameClientBuilder but i have no idea how to use that. when i tried run this code.
startActivityForResult(gameHelper.getGamesClient().getAllLeaderboardsIntent(), RC_UNUSED);
i got this log.
08-25 00:09:05.660: E/AndroidRuntime(11222): java.lang.IllegalStateException: Not connected. Call connect() and wait for onConnected() to be called.
4 . to use leaderboard i know i must use code from google play store such as CgkIx****AIQAA. but i didn't found where i must put this code to load leaderboard.
sorry for long question, but i think if there is a sample that only for connect and either access achievement or leaderboard it will answer all my question. please don't tell me to see type-a-number sample, i did that and i need another sample code.
update, my snipped code
public class MainMenu extends Activity
implements OnClickListener, GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, GameHelperListener{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_menu);
gameHelper = new GameHelper(this);
}
#Override
public void onClick(View v) {
if(v.equals(loadData)) {
if(gameHelper.isSignedIn()) {
gameHelper.setup(this, GameHelper.CLIENT_GAMES, Scopes.GAMES);
startActivityForResult(gameHelper.getGamesClient().getAllLeaderboardsIntent(), RC_UNUSED);
}
}
else if(v.equals(loginButton)) {
Intent googlePicker = AccountPicker.newChooseAccountIntent(null,null,new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE},true,null,null,null,null) ;
startActivityForResult(googlePicker, REQUEST_CODE_PICK_ACCOUNT);
}
}
#Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
if(requestCode==REQUEST_CODE_RECOVER_PLAY_SERVICES) {
if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "Google Play Services must be installed.", Toast.LENGTH_SHORT).show();
finish();
}
return;
}
else if(requestCode==REQUEST_CODE_PICK_ACCOUNT) {
if (resultCode == RESULT_OK) {
String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
gameHelper.beginUserInitiatedSignIn();
}
else if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "This application requires a Google account.", Toast.LENGTH_SHORT).show();
finish();
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
// this 2 methods not called, is this also because my code is wrong?
#Override
public void onSignInFailed() {
Log.d("rush", "on sign in failed");
}
#Override
public void onSignInSucceeded() {
Log.d("rush", "on sign in succeed");
}
}
Yes. Take a look at the BaseGameActivity source and see that it largely just wraps GameHelper. You can implement the calls to GameHelper yourself - in fact, you can probably copy some code directly from BaseGameActivity. I'm a bit confused, because it appears that your code is already using GameHelper. It looks like you are mixing GameHelper calls with BaseGameActivity calls. You cannot do this, and it will result in... errors like you are getting.
The LogCat you see means that all of your clients are connected. The default call to GameHelper.setup() just requests the Games client. If you aren't using BaseGameActivity and want different clients, do:
gameHelper = new GameHelper(this);
gameHelper.setup(this, GameHelper.CLIENT_GAMES | GameHelper.CLIENT_PLUS);
beginUserInitiatedSignIn() is an asynchronous method with a callback when it finishes. Are you running it that way? GameHelper.GameHelperListener is the interface to implement. If you are using gameHelper, make sure to register the callback. See the this in the setup call above? That's registering the callback (this is my main activity).
As I said above, it looks like you are mixing GameHelper calls with BaseGameActivity calls. The GameHelper that is connected is the BaseGameActivity.mHelper instance, not any GameHelper you might have instantiated. Make sure that if you are using BaseGameActivity that you are not using GameHelper as well.
If you want to display a single leaderboard, use the GamesClient.getLeaderboardIntent(string, int) or method to get the Intent. The string is the code you have (CgkIx****AIQAA).
startActivityForResult(gameHelper.getGamesClient().getLeaderboardIntent(
leaderboard_id, RC_UNUSED);
Again, make sure you are using the correct getGamesClient() method, depending on if you are using BaseGameActivity or GameHelper directly.
Here is basic information how to use GameHelper without BaseGameActivity:
https://developers.google.com/games/services/android/init#using_gamehelper_without_basegameactivity

Google Play Game Services & libGDX "SignInActivity must be started with startActivityForResult"

I'm trying to implement Google Play Game Services into my libGDX game. I followed the tutorial here: http://helios.hud.ac.uk/u1070589/blog/?p=202
When my game loads, I create a new GameHelper object and call its setup method. I've debugged this part and it completes without any problems. I've placed a GPGS button on my main menu, when it's clicked I call the Login() method in my main Android Activity.
At this point the mConnectionResult.startResolutionForResult(mActivity, RC_RESOLVE) call in the resolveConnectionResult method (GameHelper class) returns the error:
E/SignInActivity(21930): SignInActivity must be started with startActivityForResult
The ConnectionResult object (mConnectionResult) doesn't have a public method available called startActivityForResult so I can't just change the startResolutionForResult call.
In the beginUserInitiatedSignIn() method (GameHelper) the connection returns ConnectionResult.SUCCESS. When resolveConnectionResult() is called, mConnectionResult.hasResolution() also returns true.
I've double-checked that my debug key matches the entry for my app in the Google APIs Console. I've checked that my app ID matches the one shown on the Google Play Developer Console.
I have managed to get the Type-a-Number example app working without any problems. Here's my main Android activity:
package com.eb.droid;
import android.content.Intent;
import android.view.Window;
import android.view.WindowManager;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.swarmconnect.Swarm;
import com.eb.GoogleInterface;
import com.google.example.games.basegameutils.GameHelper;
import com.google.example.games.basegameutils.GameHelper.GameHelperListener;
public final class AndroidGame extends AndroidApplication implements GameHelperListener, GoogleInterface
{
private final int RC_RESOLVE = 5000, RC_UNUSED = 5001; //request codes we use when invoking an external activity
private final SwarmData swarmData = new SwarmData();
private GameHelper aHelper;
public AndroidGame()
{
aHelper = new GameHelper(this);
aHelper.enableDebugLog(true, "MYTAG");
}
public final void onCreate(android.os.Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
// Disable hardware functions to save battery power.
cfg.useAccelerometer = false;
cfg.useCompass = false;
cfg.useGL20 = true;
aHelper.setup(this);
setSwarmKeyPartA();
initialize(new Game(this, swarmData), cfg);
// Activate Swarm if user is already logged-in. App won't nag player to log-in, they always have to
// do it manually via the Swarn dashboard via the title screen.
//Log.d(LOG, "onCreate() Swarm.isLoggedIn() = " + Swarm.isLoggedIn());
if (Swarm.isLoggedIn())
{
Swarm.setActive(this);
}
}
public void onResume()
{
super.onResume();
if (Swarm.isLoggedIn())
{
Swarm.setActive(this);
Swarm.init(this, swarmData.swarmAppID, swarmData.swarmAppKey);
}
}
public void onPause()
{
super.onPause();
Swarm.setInactive(this);
}
#Override
ublic void onStart()
{
super.onStart();
aHelper.onStart(this);
}
#Override
public void onStop()
{
super.onStop();
aHelper.onStop();
}
#Override
public void onActivityResult(int request, int response, Intent data)
{
super.onActivityResult(request, response, data);
aHelper.onActivityResult(request, response, data);
}
public void onSignInFailed()
{
System.out.println("sign in failed");
}
public void onSignInSucceeded()
{
System.out.println("sign in succeeded");
}
public void Login()
{
try
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
aHelper.beginUserInitiatedSignIn();
}
});
}
catch (final Exception ex)
{
}
}
public void LogOut()
{
try
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
aHelper.signOut();
}
});
}
catch (final Exception ex)
{
}
}
public boolean getSignedIn()
{
return aHelper.isSignedIn();
}
public void submitScore(int _score)
{
System.out.println("in submit score");
aHelper.getGamesClient().submitScore(getString(R.string.leaderboard_high_scores), _score);
}
public void showAchievements()
{
startActivityForResult(aHelper.getGamesClient().getAchievementsIntent(), RC_UNUSED);
}
public void showLeaderboards()
{
startActivityForResult(aHelper.getGamesClient().getAllLeaderboardsIntent(), RC_UNUSED);
}
public void getScoresData()
{
}
}
My app also currently implements Swarm, as can be seen in the Activity. I tried removing Swarm to see if that was negatively affecting the GPGS login, but still no luck.
I had the same issue, then I noticed this in the logs: "Activity is launching as a new task, so cancelling activity result"
In the AndroidManifest.xml file of my libgdx game, I had set this property: 'android:launchMode="singleInstance"' As soon as I removed that, I was able to use GPGS just like the sample apps.
I haven't looked at your code in detail. Basically I used the supplied GameHelper (I think you have done the same) and I put everything I needed from BaseGameUtils in my fragments. I suggest you look at a successful trace from TypeANumber to see what you are missing. Here is one of my traces:
07-04 10:21:54.511: D/ian_(1781): MultiTab3 beginUserInitiatedSignIn
04 10:21:54.531: D/ian_(1781): isGooglePlayServicesAvailable returned 0
07-04 10:21:54.531: D/ian_(1781): beginUserInitiatedSignIn: continuing pending sign-in flow.
07-04 10:21:54.611: D/ian_(1781): resolveConnectionResult: trying to resolve result: C onnectionResult{statusCode=SIGN_IN_REQUIRED, resolution=PendingIntent{40f3ed38: android.os.BinderProxy#40ee3de0}}
07-04 10:21:54.611: D/ian_(1781): result has resolution. Starting it.
07-04 10:21:54.621: D/ian_(1781): startResolutionForResult - this may be prob ?
07-04 10:23:29.480: D/ian_(1781): MultiPlayer onActivityResult called9001-1null
07-04 10:23:29.520: D/ian_(1781): MultiPlayer passing onActivityResult to MultiTab3 Req/Resp/Data=9001-1null
07-04 10:23:29.520: D/ian_(1781): MultiTab3 onActivityResult - passing through to GameHelper ...9001-1null
07-04 10:23:29.520: D/ian_(1781): onActivityResult, req 9001 response -1
07-04 10:23:29.520: D/ian_(1781): responseCode == RESULT_OK. So connecting.
07-04 10:23:30.130: D/ian_(1781): onConnected: connected! client=1
07-04 10:23:30.130: D/ian_(1781): All clients now connected. Sign-in successful.
07-04 10:23:30.130: D/ian_(1781): All requested clients connected. Sign-in succeeded!
Update:
What about this - is this just a copy and paste error or is your program missing the "P" on Public ? (You do need to make this call)
#Override
ublic void onStart()
{
super.onStart();
aHelper.onStart(this);
}
Update 2:
Based on the work you have done, you have now eliminated the possibility of a programming error. I have not seen a setup error that caused this problem. However I did encounter this which is (sort of) similar:
onConnectionFailed: result 4
onConnectionFailed: since user initiated sign-in, trying to resolve problem
statusCode=SIGN_IN_REQUIRED resolution=PendingIntent
result has resolution. Starting it.
Explanation from google docs "The client attempted to connect to the service but the user is not signed in"
n.b. Google setting is showing that we are signed in as ..........#gmail.com
further investigation **suggests** that this may be because of a set up problem in the
google play api console and/or google play developer console ...
I also notice that you mentioned the Google API console. I suggest you create a new set of definitions in the Developer Console and that you do not make any amendments through the API console. I am not saying that you have changed things in the API console - I just think it is easier at this point to create a new set of definitions and (I'm repeating myself I know) don't make any changes through the API console.

Android not acknowledging TTS Engine

I am developing a very simple app in here. It's for my Cerebral Palsy daughter. It's just a big YES and NO buttons, so she can press them when requested.
Well... I am using SVOX Classic TTS Engine.
Everything was running smoothly until my tablet upgraded to ICS. Now, everytime I run the app, it opens the Market asking for me to install TTS. I hit "back" and then, my app speaks. This is VERY annoying.
Here is what Google API says:
*A successful check will be marked by a CHECK_VOICE_DATA_PASS result code, indicating this device is ready to speak, after the creation of our TextToSpeech object. If not, we need to let the user know to install the data that's required for the device to become a multi-lingual talking machine! Downloading and installing the data is accomplished by firing off the ACTION_INSTALL_TTS_DATA intent, which will take the user to Android Market, and will let her/him initiate the download. Installation of the data will happen automatically once the download completes. Here is an example of what your implementation of onActivityResult() would look like:*
Here is my code:
public class yesOunoActivity extends Activity implements OnInitListener{
ImageView yes;
ImageView no;
public TextToSpeech tts;
private int MY_DATA_CHECK_CODE = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
tts = new TextToSpeech(this, this);
setContentView(R.layout.yesorno);
yes = (ImageView) findViewById(R.id.yes);
no = (ImageView) findViewById(R.id.no);
yes.setClickable(true);
yes.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent arg1) {
if (arg1.getAction() == android.view.MotionEvent.ACTION_DOWN) {
tts.speak("yes!", TextToSpeech.QUEUE_ADD, null);
}
return true;
}
});
no.setClickable(true);
no.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent arg1) {
if (arg1.getAction() == android.view.MotionEvent.ACTION_DOWN) {
//Intent myIntent = new Intent(v.getContext(), ParametrosActivity.class);
tts.speak("no!", TextToSpeech.QUEUE_ADD, null);
}
return true;
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MY_DATA_CHECK_CODE) {
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
// success, create the TTS instance
tts = new TextToSpeech(this, this);
} else {
// missing data, install it
//ATTENTION: BELOW THIS GIVES ME PROBLEMS SINCE IT OPENS MARKET
//AND I HAVE TO HIT THE BACK BUTTON, THEN, IT SPEAKS!
//BTW TTS ENGINE "IS" INSTALLED!!
Intent installIntent = new Intent();
installIntent
.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
}
}
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
} else if (status == TextToSpeech.ERROR) {
}
}
#Override
public void onDestroy() {
if (tts != null) {
tts.stop();
tts.shutdown();
}
super.onDestroy();
System.gc();
}
}
If I remove the area with "ATTENTION" above (since I am SURE I have TTS installed), it works the first time I run the app, if I leave the app and I open it again, it says "speak failed: not bound to tts engine"
It's like it doesn't create the TTS object since the app is still in memory.
So, guys... what do you guys think that I should do??
This is driving me crazy and I really need to communicate to my daughter through the tablet!
Any help is appreciated!!
I had this trouble on my application as well: TTS works in 2.3, but when I tried 4.0, it had the same symptoms as your problem (which I just found now while searching for a solution). The engine would work if you force-closed the application through Settings and started it again but just "backing out" and going back made the TTS engine in ICS not bind.
I tried setting the TTS object (mTts) to null after running mTts.shutdown(). When I started the application again after backing out, I got a null error on my mTts.speak() line.
At least for ICS, something is not letting go of the TTS engine. My solution (for now) is that I have made my TTS object static:
// in Activity
private static TextToSpeech mTts;
.
.
.
// in onCreate()
mTts = new TextToSpeech(this, this);
.
.
.
// in onDestroy()
if (mTts != null) {
mTts.stop();
mTts.shutdown();
mTts = null;
}
I was already only using one TTS object for the application so I don't think there are too many downsides to this approach.
This is what I have in onActivityResult(...)
#Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
if (requestCode == MY_DATA_CHECK_CODE) {
/*
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
// success, create the TTS instance
mTts = new TextToSpeech(this, this);
} else {
// missing data, install it
Intent installIntent = new Intent();
installIntent.setAction(
TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
*/
if (mTts==null) {
Intent installIntent = new Intent();
installIntent.setAction(
TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
mTts = new TextToSpeech(this, this);
}
}
Instead of using if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {...}, I check if mTts has already been instantiated. You'll also have to set mTts as static, as was mentioned by jlquant and Rakesh in an earlier post, so you'll have only a single instance of it. For example, private static TextToSpeech mTts.
So, unless you "Force stop" the app or it stops working because of an error, it won't anymore call the startActivity(installIntent);-- the annoying culprit that asks you to install TTS every time.
I fixed this by installing ivona having both Tts engines cured all problems, though I'm finding other issues such as no default tts is installed using the two together makes one work not a great fix but its s fix,
Also I can't find the option to allow my phone to install non market apps ie apk from my SD card
I had the same problem and solved. Maybe it's a timing issue in bounding, not sure, but a simple action before speak helped me.
Anyway I did this:
mTts = new TextToSpeech(this, this);
String engine = mTts.getDefaultEngine();
mTts = new TextToSpeech(this, this,engine);
Log.d("","...something here...");
Then when I hit my speak button, it speaks. You should watch your variable status on OnInit method. Maybe a separate thread can help talking in the app.
By the way, if you are sure TTS is installed, you can remove the block Intent checkIntent = new Intent(); for checking.
I definitely hope this helps you.
in my app I also used checkintent.setAction(...) to check if the necessary tts files are installed (which was working like a charm before upgrading to ICS). In ICS it always returned that the files are missing. So now I just ignore this check: i am creating the object and it initializes fine.
Moreover I was using two instances for two different languages. This also seems to not work anymore.
Now when I set the language for one of the instances, the other instance of the object is set to the same language (behaves like one instance).
gingerbread allowed setting of default tts in voice input& output / default tts
gingerbread only allows 'preferred' tts in language and input / text to speech output.
so tts is preferred instead of default, which just means it is not as clear as to which gets used.
The default with application overrides where stated is a better option I think.

Categories

Resources