1337ingDisorder
1337ingDisorder

Reputation: 893

Can't create handler inside thread that has not called Looper.prepare() for Rate Me dialog

I'm trying to implement a "Rate Me" dialog in a game I'm working on, as per the instructions on this page:

http://www.androidsnippets.com/prompt-engaged-users-to-rate-your-app-in-the-android-market-appirater

I think I've implemented everything according to the instructions provided, but when I call the AppRater.showRateDialog(this, null) method my game crashes and I get the following error output in LogCat:

06-20 19:29:34.622: E/AndroidRuntime(25236): FATAL EXCEPTION: GLThread 6087
06-20 19:29:34.622: E/AndroidRuntime(25236): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
06-20 19:29:34.622: E/AndroidRuntime(25236):    at android.os.Handler.<init>(Handler.java:121)
06-20 19:29:34.622: E/AndroidRuntime(25236):    at android.app.Dialog.<init>(Dialog.java:114)
06-20 19:29:34.622: E/AndroidRuntime(25236):    at android.app.Dialog.<init>(Dialog.java:138)
06-20 19:29:34.622: E/AndroidRuntime(25236):    at com.kittykazoo.distantshores.android.AppRater.showRateDialog(AppRater.java:45)
06-20 19:29:34.622: E/AndroidRuntime(25236):    at com.kittykazoo.helpers.InputPoller.updateMainMenu(InputPoller.java:140)
06-20 19:29:34.622: E/AndroidRuntime(25236):    at com.kittykazoo.helpers.InputPoller.update(InputPoller.java:68)
06-20 19:29:34.622: E/AndroidRuntime(25236):    at com.kittykazoo.gameworld.GameWorld.update(GameWorld.java:141)
06-20 19:29:34.622: E/AndroidRuntime(25236):    at com.kittykazoo.screens.GameScreen.render(GameScreen.java:20)
06-20 19:29:34.622: E/AndroidRuntime(25236):    at com.badlogic.gdx.Game.render(Game.java:46)
06-20 19:29:34.622: E/AndroidRuntime(25236):    at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:422)
06-20 19:29:34.622: E/AndroidRuntime(25236):    at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
06-20 19:29:34.622: E/AndroidRuntime(25236):    at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)

Here's the source code for my main Android class:

public class AndroidLauncher extends AndroidApplication {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
        DistantShores ds = new DistantShores();
        initialize(ds, config);

        // Designate AppRater
        DistantShores.setAppRater(new AppRater(this));

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

}

...and the source code for the AppRater class:

public class AppRater implements AppRaterInterface {

private Activity mContext;
SharedPreferences prefs;
SharedPreferences.Editor editor;
private Button b1, b2, b3;

public AppRater(Activity mContext) {
    this.mContext = mContext;
    prefs = mContext.getSharedPreferences("kk_distantshores_apprater", 0);
    editor = prefs.edit();
}

public boolean isTimeoutElapsed() {
    if (prefs.getLong("lastShow", System.currentTimeMillis()) >= TIMEOUT)
        return true;
    return false;
}

public void showRateDialog() {

    if (prefs.getBoolean("dontshowagain", false)) {
        return;
    }

    editor.putLong("lastShow", System.currentTimeMillis());

    final Dialog dialog = new Dialog(mContext);
    dialog.setTitle("Rate " + APP_TITLE);

    LinearLayout ll = new LinearLayout(mContext);
    ll.setOrientation(LinearLayout.VERTICAL);

    final TextView tv = new TextView(mContext);
    tv.setText("If you enjoy using " + APP_TITLE
            + ", please take a moment to rate it. Thanks for your support!");
    tv.setWidth(240);
    tv.setPadding(4, 0, 4, 10);
    ll.addView(tv);

    b1 = new Button(mContext);
    b1.setText("Rate " + APP_TITLE);
    b1.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {

            final Uri uri = Uri.parse("market://details?id=" + APP_PNAME);
            final Intent rateAppIntent = new Intent(Intent.ACTION_VIEW, uri);

            if (mContext.getPackageManager().queryIntentActivities(rateAppIntent, 0).size() > 0) {
                mContext.startActivity(rateAppIntent);
                dialog.dismiss();
            } else {

                /* the device has no way to handle market urls */

                dialog.setTitle("Error!");
                tv.setText("No Market app detected. In order to rate this app the Google Play Store must be installed.");
                b1.setVisibility(View.GONE);
                b2.setVisibility(View.GONE);
                b3.setText("Cancel");

            }

        }
    });
    ll.addView(b1);

    b2 = new Button(mContext);
    b2.setText("Remind me later");
    b2.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            dialog.dismiss();
        }
    });
    ll.addView(b2);

    b3 = new Button(mContext);
    b3.setText("No, thanks");
    b3.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            if (editor != null) {
                editor.putBoolean("dontshowagain", true);
                editor.commit();
            }
            dialog.dismiss();
        }
    });
    ll.addView(b3);

    dialog.setContentView(ll);
    dialog.show();

}

}

Upvotes: 0

Views: 95

Answers (2)

1337ingDisorder
1337ingDisorder

Reputation: 893

I managed to get it working by encapsulating the dialog code in a runOnUiThread() instance

Upvotes: 0

siva
siva

Reputation: 1858

Your dialogue needs an activity context, looks like you are creating the dialogue in non-ui thread. Please check which context you are passing to dialogue constructor.

Upvotes: 1

Related Questions